parent
132ea41f5b
commit
90e3182d89
7 changed files with 1202 additions and 1 deletions
@ -0,0 +1,164 @@ |
|||||||
|
<template> |
||||||
|
<div id="3d-graph"></div> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script lang="ts" setup> |
||||||
|
// import { useRouter } from 'vue-router' |
||||||
|
import { onMounted, ref, reactive, watch } from 'vue' |
||||||
|
import ForceGraph3D from '3d-force-graph' |
||||||
|
//@ts-ignore |
||||||
|
import { |
||||||
|
CSS2DRenderer, |
||||||
|
CSS2DObject, |
||||||
|
} from 'three/examples/jsm/renderers/CSS2DRenderer.js' |
||||||
|
//@ts-ignore |
||||||
|
import SpriteText from '../spritetext.js' |
||||||
|
// const $router = useRouter() |
||||||
|
// const jsonData = ref(null) |
||||||
|
let Graph: any = reactive({}) |
||||||
|
const props = defineProps({ |
||||||
|
width: { |
||||||
|
type: Number, |
||||||
|
default: |
||||||
|
window.innerWidth || |
||||||
|
document.documentElement.clientWidth || |
||||||
|
document.body.clientWidth, |
||||||
|
}, |
||||||
|
height: { |
||||||
|
type: Number, |
||||||
|
default: |
||||||
|
window.innerHeight || |
||||||
|
document.documentElement.clientHeight || |
||||||
|
document.body.clientHeight, |
||||||
|
}, |
||||||
|
}) |
||||||
|
watch( |
||||||
|
() => props.width, |
||||||
|
(ne) => Graph.width(ne), |
||||||
|
) |
||||||
|
watch( |
||||||
|
() => props.height, |
||||||
|
(ne) => Graph.height(ne), |
||||||
|
) |
||||||
|
const dom = ref(null) |
||||||
|
onMounted(() => { |
||||||
|
Graph = ForceGraph3D({ |
||||||
|
extraRenderers: [new CSS2DRenderer()], |
||||||
|
})(document.getElementById('3d-graph') as HTMLElement) |
||||||
|
.jsonUrl('../../../public/data.json') |
||||||
|
// .nodeAutoColorBy('group') |
||||||
|
.nodeThreeObject((node: any) => { |
||||||
|
const nodeEl = document.createElement('div') |
||||||
|
nodeEl.textContent = node.label |
||||||
|
nodeEl.style.color = '#333333' |
||||||
|
nodeEl.style.borderRadius = '50%' |
||||||
|
// console.log(node, 111, Graph.graphData().nodes) |
||||||
|
return new CSS2DObject(nodeEl) |
||||||
|
}) |
||||||
|
.linkLabel((link: any) => link.label) // 指定链接上显示的文字属性 |
||||||
|
.linkWidth(0.8) |
||||||
|
.linkHoverPrecision(0.5) // 设置链接文字的显示精度,这里设置为一个足够小的值 |
||||||
|
.linkColor(() => '#dd92fd') // 设置连接线颜色为红色 |
||||||
|
.backgroundColor('#f5f6fd') |
||||||
|
.width(props.width) |
||||||
|
.height(props.height) |
||||||
|
.linkThreeObjectExtend(true) |
||||||
|
.nodeColor((node: any) => { |
||||||
|
return node.color |
||||||
|
}) |
||||||
|
.nodeRelSize(7) // 设置节点的相对大小为4 |
||||||
|
.nodeResolution(20) |
||||||
|
.linkDirectionalArrowLength(3) // 设置连接线箭头长度为3 |
||||||
|
.linkDirectionalArrowRelPos(1) // 设置连接线箭头位置为连接线末端 |
||||||
|
.nodeThreeObjectExtend(true) |
||||||
|
.onNodeClick((node: any) => { |
||||||
|
// Aim at node from outside it |
||||||
|
// 目标距离 |
||||||
|
const targetDistance = 200 // 设定一个一般的距离 |
||||||
|
|
||||||
|
// 计算相机新位置 |
||||||
|
const distRatio = 1 + targetDistance / Math.hypot(node.x, node.y, node.z) |
||||||
|
const newPos = { |
||||||
|
x: node.x * distRatio, |
||||||
|
y: node.y * distRatio, |
||||||
|
z: node.z * distRatio, |
||||||
|
} |
||||||
|
|
||||||
|
// 如果节点位于原点,则特殊处理 |
||||||
|
if (node.x === 0 && node.y === 0 && node.z === 0) { |
||||||
|
newPos.z = targetDistance // 将 z 轴设定为目标距离 |
||||||
|
} |
||||||
|
|
||||||
|
// 移动相机至新位置 |
||||||
|
//@ts-ignore |
||||||
|
Graph.cameraPosition( |
||||||
|
newPos, // 新位置 |
||||||
|
node, // 视角焦点 |
||||||
|
3000, // 过渡时长 |
||||||
|
) |
||||||
|
|
||||||
|
// 获取图表数据 |
||||||
|
//@ts-ignore |
||||||
|
const graphData = Graph.graphData() |
||||||
|
|
||||||
|
// 遍历连接线,检查每条连接线的起点和终点是否与当前点击的节点相关联 |
||||||
|
graphData.links.forEach((link: any) => { |
||||||
|
// console.log(link); |
||||||
|
|
||||||
|
if (link.source.id === node.id || link.target.id === node.id) { |
||||||
|
setLabel() |
||||||
|
// 将与当前点击节点相关联的连接线颜色设置为红色 |
||||||
|
// link.color = '#FF0000' // 设置连接线颜色为红色 |
||||||
|
//@ts-ignore |
||||||
|
Graph.linkColor((item: any): any => { |
||||||
|
if (item.source.id === node.id || item.target.id === node.id) { |
||||||
|
return 'red' |
||||||
|
} else { |
||||||
|
return '#dd92fd' |
||||||
|
} |
||||||
|
}) |
||||||
|
} else { |
||||||
|
// Graph.linkColor(() => '#a4c7fe') // 设置连接线颜色为红色 |
||||||
|
} |
||||||
|
}) |
||||||
|
|
||||||
|
// 更新图形数据,以应用颜色变化 |
||||||
|
//@ts-ignore |
||||||
|
Graph.graphData(graphData) |
||||||
|
}) |
||||||
|
dom.value = document.querySelector('canvas') as any |
||||||
|
}) |
||||||
|
|
||||||
|
const setLabel = () => { |
||||||
|
//@ts-ignore |
||||||
|
Graph.linkThreeObject((link: any) => { |
||||||
|
// extend link with text sprite |
||||||
|
const sprite = new SpriteText(`${link.label}`) |
||||||
|
sprite.color = '#ccc' |
||||||
|
sprite.textHeight = 1.5 |
||||||
|
return sprite |
||||||
|
}) |
||||||
|
//@ts-ignore |
||||||
|
Graph.linkPositionUpdate((sprite, { start, end }) => { |
||||||
|
//@ts-ignore |
||||||
|
const middlePos = Object.assign( |
||||||
|
...['x', 'y', 'z'].map((c) => ({ |
||||||
|
//@ts-ignore |
||||||
|
[c]: start[c] + (end[c] - start[c]) / 2, // calc middle point |
||||||
|
})), |
||||||
|
) |
||||||
|
|
||||||
|
// Position sprite |
||||||
|
Object.assign(sprite.position, middlePos) |
||||||
|
}) |
||||||
|
//@ts-ignore |
||||||
|
Graph.d3Force('charge').strength(-120) |
||||||
|
} |
||||||
|
// const goToEditAtlas = () => { |
||||||
|
// console.log(jsonData.value) |
||||||
|
|
||||||
|
// $router.push({ name: 'EditAtlas', params: { id: 123 } }) |
||||||
|
// } |
||||||
|
</script> |
||||||
|
|
||||||
|
<style lang="scss" scoped></style> |
@ -0,0 +1,46 @@ |
|||||||
|
<template> |
||||||
|
<div class="atlas-ui" ref="atlas"> |
||||||
|
<professionalProfile v-bind="atlasAttribute" /> |
||||||
|
<div class="on-off" @click="() => $emit('hadRouter')"> |
||||||
|
<el-icon> |
||||||
|
<Right /> |
||||||
|
</el-icon> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
<script lang="ts" setup> |
||||||
|
import { ref, reactive, onMounted } from 'vue' |
||||||
|
import professionalProfile from './KnowledgeGraph.vue' |
||||||
|
const $emit = defineEmits(['hadRouter']) |
||||||
|
const atlas = ref(null) |
||||||
|
const atlasAttribute = reactive({ width: 0, height: 0 }) |
||||||
|
onMounted(() => { |
||||||
|
const el: HTMLElement = atlas.value! |
||||||
|
const width = +getComputedStyle(el).width.slice(0, -2) |
||||||
|
const height = +getComputedStyle(el).height.slice(0, -2) |
||||||
|
atlasAttribute.width = width |
||||||
|
atlasAttribute.height = height |
||||||
|
}) |
||||||
|
</script> |
||||||
|
<style lang="scss"> |
||||||
|
.atlas-ui { |
||||||
|
width: 100%; |
||||||
|
height: 100%; |
||||||
|
position: relative; |
||||||
|
overflow: hidden; |
||||||
|
&:hover .on-off { |
||||||
|
transform: translate(0%); |
||||||
|
padding-right: 10px; |
||||||
|
} |
||||||
|
|
||||||
|
.on-off { |
||||||
|
position: absolute; |
||||||
|
top: 0; |
||||||
|
right: 0; |
||||||
|
cursor: pointer; |
||||||
|
padding-top: 5px; |
||||||
|
transform: translate(100%); |
||||||
|
transition: all 0.3s; |
||||||
|
} |
||||||
|
} |
||||||
|
</style> |
@ -0,0 +1,190 @@ |
|||||||
|
<template> |
||||||
|
<div class="look-resource-ui" ref="atlas"> |
||||||
|
<div class="head"> |
||||||
|
<div class="log"></div> |
||||||
|
<div class="text">查看资源</div> |
||||||
|
</div> |
||||||
|
<div class="con" v-for="item in 5" :key="item"> |
||||||
|
<div class="chapter-box"> |
||||||
|
<div class="left">第一章</div> |
||||||
|
<div class="right">第二小节</div> |
||||||
|
</div> |
||||||
|
<div class="detailedness-chapter-box"> |
||||||
|
<div class="left"> |
||||||
|
<div class="vertical-dotted-line"></div> |
||||||
|
</div> |
||||||
|
<div class="right"> |
||||||
|
<div class="top">知识点</div> |
||||||
|
<div class="center">知识点详情,知识点内容</div> |
||||||
|
<div class="bottom"> |
||||||
|
<div class="img-box"></div> |
||||||
|
<div class="info-box"> |
||||||
|
<div class="text-name">知识点清单.pdf</div> |
||||||
|
<div class="text-size">15M</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
<script lang="ts" setup> |
||||||
|
const props = defineProps(['lookResource']) |
||||||
|
console.log(props.lookResource, '查看资源接口数据') |
||||||
|
</script> |
||||||
|
<style lang="scss"> |
||||||
|
.look-resource-ui { |
||||||
|
$padding-left: 18px; |
||||||
|
width: 100%; |
||||||
|
height: 100%; |
||||||
|
background-color: #fff; |
||||||
|
padding: 24px 22px 0 $padding-left; |
||||||
|
display: flex; |
||||||
|
flex-direction: column; |
||||||
|
|
||||||
|
.head { |
||||||
|
$height: 30px; |
||||||
|
display: flex; |
||||||
|
margin-bottom: 32px; |
||||||
|
|
||||||
|
.log { |
||||||
|
width: $height; |
||||||
|
height: $height; |
||||||
|
background: #4782ff; |
||||||
|
border-radius: 4px; |
||||||
|
margin-right: 12px; |
||||||
|
} |
||||||
|
|
||||||
|
.text { |
||||||
|
font-weight: bold; |
||||||
|
font-size: 20px; |
||||||
|
color: #333333; |
||||||
|
line-height: $height; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
.con { |
||||||
|
& > * { |
||||||
|
display: flex; |
||||||
|
} |
||||||
|
|
||||||
|
$width: 51px; |
||||||
|
|
||||||
|
.chapter-box { |
||||||
|
$line-height: 22px; |
||||||
|
margin-bottom: 12px; |
||||||
|
|
||||||
|
.left { |
||||||
|
min-width: $width; |
||||||
|
height: 22px; |
||||||
|
margin-right: 16px; |
||||||
|
font-weight: 400; |
||||||
|
font-size: 16px; |
||||||
|
color: #333333; |
||||||
|
line-height: $line-height; |
||||||
|
} |
||||||
|
|
||||||
|
.right { |
||||||
|
line-height: $line-height; |
||||||
|
font-weight: 400; |
||||||
|
font-size: 14px; |
||||||
|
color: #9a9a9a; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
.detailedness-chapter-box { |
||||||
|
.left { |
||||||
|
width: $width; |
||||||
|
|
||||||
|
.vertical-dotted-line { |
||||||
|
height: 168px; |
||||||
|
margin-left: calc(53px - $padding-left); |
||||||
|
border-left: 1px dotted #d9d9d9; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
.right { |
||||||
|
display: flex; |
||||||
|
flex-direction: column; |
||||||
|
|
||||||
|
& > * { |
||||||
|
margin-bottom: 15px; |
||||||
|
} |
||||||
|
|
||||||
|
& > *:last-child { |
||||||
|
margin-bottom: 0; |
||||||
|
} |
||||||
|
|
||||||
|
.top { |
||||||
|
$height: 17px; |
||||||
|
width: 53px; |
||||||
|
height: $height; |
||||||
|
line-height: $height; |
||||||
|
text-align: center; |
||||||
|
background: #5ee183; |
||||||
|
border-radius: 2px; |
||||||
|
font-weight: 400; |
||||||
|
font-size: 12px; |
||||||
|
color: #ffffff; |
||||||
|
} |
||||||
|
|
||||||
|
.center { |
||||||
|
$height: 22px; |
||||||
|
height: $height; |
||||||
|
line-height: $height; |
||||||
|
font-weight: 400; |
||||||
|
font-size: 16px; |
||||||
|
color: #333333; |
||||||
|
} |
||||||
|
|
||||||
|
.bottom { |
||||||
|
width: 243px; |
||||||
|
height: 84px; |
||||||
|
background: rgba(255, 255, 255, 0.5); |
||||||
|
border-radius: 4px; |
||||||
|
border: 1px solid #d9d9d9; |
||||||
|
cursor: pointer; |
||||||
|
transition: 0.3s; |
||||||
|
padding: 17px 0 17px 20px; |
||||||
|
display: flex; |
||||||
|
|
||||||
|
&:hover { |
||||||
|
border: 1px solid #6997fa; |
||||||
|
} |
||||||
|
|
||||||
|
.img-box { |
||||||
|
width: 42px; |
||||||
|
height: 50px; |
||||||
|
background: #4d4d4d; |
||||||
|
margin-right: 23px; |
||||||
|
} |
||||||
|
|
||||||
|
.info-box { |
||||||
|
display: flex; |
||||||
|
flex-direction: column; |
||||||
|
$height: 22px; |
||||||
|
|
||||||
|
& > * { |
||||||
|
height: $height; |
||||||
|
line-height: $height; |
||||||
|
} |
||||||
|
|
||||||
|
.text-name { |
||||||
|
font-weight: 400; |
||||||
|
font-size: 12px; |
||||||
|
color: #333333; |
||||||
|
margin-bottom: 6px; |
||||||
|
} |
||||||
|
|
||||||
|
.text-size { |
||||||
|
font-weight: 400; |
||||||
|
font-size: 12px; |
||||||
|
color: #9a9a9a; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
</style> |
@ -0,0 +1,149 @@ |
|||||||
|
<template> |
||||||
|
<div class="container"> |
||||||
|
<div class="left"> |
||||||
|
<div class="ratio"> |
||||||
|
<div class="abso"> |
||||||
|
<div class="atlas center"> |
||||||
|
<atlas-ui @hadRouter="handle" /> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
|
||||||
|
<div class="cut"> |
||||||
|
<div class="cut_nav" :onclick="hClick"> |
||||||
|
<div data-i="0" class="active">视频</div> |
||||||
|
<div data-i="1">视频</div> |
||||||
|
<div data-i="2">视频</div> |
||||||
|
<div data-i="3">视频</div> |
||||||
|
<div data-i="4">视频</div> |
||||||
|
</div> |
||||||
|
<div class="con center"> |
||||||
|
<div v-if="cutI == '0'">课程资源0</div> |
||||||
|
<div v-if="cutI == '1'">课程资源1</div> |
||||||
|
<div v-if="cutI == '2'">课程资源2</div> |
||||||
|
<div v-if="cutI == '3'">课程资源3</div> |
||||||
|
<div v-if="cutI == '4'">课程资源4</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
<div class="right"> |
||||||
|
<div class="info center">课程基本信息</div> |
||||||
|
<div class="chapter center"> |
||||||
|
<look-resource-ui :lookResource="lookResource" /> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script lang='ts' setup> |
||||||
|
function hasChanged(x: any, y: any) { |
||||||
|
if (x === y) return x === 0 && 1 / x !== 1 / y |
||||||
|
else return x === x || y === y |
||||||
|
} |
||||||
|
import lookResourceUi from './components/lookResourceUi.vue'; |
||||||
|
import atlasUi from './components/atlasUi.vue'; |
||||||
|
import { useRouter } from 'vue-router' |
||||||
|
|
||||||
|
import { ref,reactive } from 'vue' |
||||||
|
|
||||||
|
// 切换 |
||||||
|
const cutI = ref('0') |
||||||
|
function hClick(e: any) { |
||||||
|
let i = e.target.dataset.i |
||||||
|
if (!hasChanged(i, cutI.value)) return |
||||||
|
// @ts-ignore |
||||||
|
for (const d of this?.children) d.classList.remove('active') |
||||||
|
if (i) (e.target as Element).classList.add('active') |
||||||
|
cutI.value = i |
||||||
|
} |
||||||
|
|
||||||
|
// 知识图谱 |
||||||
|
const $router = useRouter() |
||||||
|
const handle = () =>{/* $router.push('/knowledgeAtlas')*/} |
||||||
|
|
||||||
|
// 章节 |
||||||
|
const lookResource: any = reactive({}) |
||||||
|
</script> |
||||||
|
|
||||||
|
<style lang='scss' scoped> |
||||||
|
.center { |
||||||
|
display: flex; |
||||||
|
justify-content: center; |
||||||
|
align-items: center; |
||||||
|
} |
||||||
|
|
||||||
|
.container { |
||||||
|
padding: 120px 20px 0; |
||||||
|
display: grid; |
||||||
|
grid-template-columns: 6fr 4fr; |
||||||
|
$gap: 5px; |
||||||
|
column-gap: $gap; |
||||||
|
|
||||||
|
.left { |
||||||
|
|
||||||
|
.ratio { |
||||||
|
margin-bottom: $gap; |
||||||
|
display: flow-root; |
||||||
|
width: 100%; |
||||||
|
|
||||||
|
.abso { |
||||||
|
position: relative; |
||||||
|
width: 100%; |
||||||
|
padding-top: 50%; |
||||||
|
|
||||||
|
.atlas { |
||||||
|
position: absolute; |
||||||
|
inset: 0; |
||||||
|
background-color: #ccc; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
.cut { |
||||||
|
height: 500px; |
||||||
|
display: flex; |
||||||
|
flex-direction: column; |
||||||
|
padding-top: 2px; |
||||||
|
padding-left: 2px; |
||||||
|
background-color: #ccc; |
||||||
|
|
||||||
|
.cut_nav { |
||||||
|
$h: 50px; |
||||||
|
display: flex; |
||||||
|
height: $h; |
||||||
|
|
||||||
|
|
||||||
|
&>* { |
||||||
|
cursor: pointer; |
||||||
|
width: 100px; |
||||||
|
text-align: center; |
||||||
|
background-color: #ccc; |
||||||
|
line-height: $h; |
||||||
|
border-top-left-radius: 5%; |
||||||
|
border-top-right-radius: 5%; |
||||||
|
box-shadow: 0px 0px 0px 2px #919191; |
||||||
|
|
||||||
|
&.active { |
||||||
|
background-color: #fff; |
||||||
|
box-shadow: 0px -1px 0px 1px #919191; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
.con { |
||||||
|
flex-grow: 1; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
.right { |
||||||
|
display: grid; |
||||||
|
grid-template-rows: 480px auto; |
||||||
|
row-gap: $gap; |
||||||
|
|
||||||
|
&>* { |
||||||
|
background-color: #ccc; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
</style> |
@ -0,0 +1,641 @@ |
|||||||
|
import { |
||||||
|
LinearFilter, |
||||||
|
Sprite, |
||||||
|
SpriteMaterial, |
||||||
|
SRGBColorSpace, |
||||||
|
Texture, |
||||||
|
} from 'three' |
||||||
|
|
||||||
|
function _callSuper(t, o, e) { |
||||||
|
return ( |
||||||
|
(o = _getPrototypeOf(o)), |
||||||
|
_possibleConstructorReturn( |
||||||
|
t, |
||||||
|
_isNativeReflectConstruct() |
||||||
|
? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) |
||||||
|
: o.apply(t, e), |
||||||
|
) |
||||||
|
) |
||||||
|
} |
||||||
|
function _isNativeReflectConstruct() { |
||||||
|
try { |
||||||
|
let t = !Boolean.prototype.valueOf.call( |
||||||
|
Reflect.construct(Boolean, [], function () {}), |
||||||
|
) |
||||||
|
} catch (t) {} |
||||||
|
return (_isNativeReflectConstruct = function () { |
||||||
|
return !!t |
||||||
|
})() |
||||||
|
} |
||||||
|
function _iterableToArrayLimit(r, l) { |
||||||
|
let t = |
||||||
|
null == r |
||||||
|
? null |
||||||
|
: ('undefined' != typeof Symbol && r[Symbol.iterator]) || r['@@iterator'] |
||||||
|
if (null != t) { |
||||||
|
let e, |
||||||
|
n, |
||||||
|
i, |
||||||
|
u, |
||||||
|
a = [], |
||||||
|
f = !0, |
||||||
|
o = !1 |
||||||
|
try { |
||||||
|
if (((i = (t = t.call(r)).next), 0 === l)) { |
||||||
|
if (Object(t) !== t) return |
||||||
|
f = !1 |
||||||
|
} else |
||||||
|
for ( |
||||||
|
; |
||||||
|
!(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); |
||||||
|
f = !0 |
||||||
|
); |
||||||
|
} catch (r) { |
||||||
|
;(o = !0), (n = r) |
||||||
|
} finally { |
||||||
|
try { |
||||||
|
if (!f && null != t.return && ((u = t.return()), Object(u) !== u)) |
||||||
|
return |
||||||
|
} finally { |
||||||
|
if (o) throw n |
||||||
|
} |
||||||
|
} |
||||||
|
return a |
||||||
|
} |
||||||
|
} |
||||||
|
function _toPrimitive(t, r) { |
||||||
|
if ('object' != typeof t || !t) return t |
||||||
|
let e = t[Symbol.toPrimitive] |
||||||
|
if (void 0 !== e) { |
||||||
|
let i = e.call(t, r || 'default') |
||||||
|
if ('object' != typeof i) return i |
||||||
|
throw new TypeError('@@toPrimitive must return a primitive value.') |
||||||
|
} |
||||||
|
return ('string' === r ? String : Number)(t) |
||||||
|
} |
||||||
|
function _toPropertyKey(t) { |
||||||
|
let i = _toPrimitive(t, 'string') |
||||||
|
return 'symbol' == typeof i ? i : String(i) |
||||||
|
} |
||||||
|
function _classCallCheck(instance, Constructor) { |
||||||
|
if (!(instance instanceof Constructor)) { |
||||||
|
throw new TypeError('Cannot call a class as a function') |
||||||
|
} |
||||||
|
} |
||||||
|
function _defineProperties(target, props) { |
||||||
|
for (let i = 0; i < props.length; i++) { |
||||||
|
let descriptor = props[i] |
||||||
|
descriptor.enumerable = descriptor.enumerable || false |
||||||
|
descriptor.configurable = true |
||||||
|
if ('value' in descriptor) descriptor.writable = true |
||||||
|
Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor) |
||||||
|
} |
||||||
|
} |
||||||
|
function _createClass(Constructor, protoProps, staticProps) { |
||||||
|
if (protoProps) _defineProperties(Constructor.prototype, protoProps) |
||||||
|
if (staticProps) _defineProperties(Constructor, staticProps) |
||||||
|
Object.defineProperty(Constructor, 'prototype', { |
||||||
|
writable: false, |
||||||
|
}) |
||||||
|
return Constructor |
||||||
|
} |
||||||
|
function _inherits(subClass, superClass) { |
||||||
|
if (typeof superClass !== 'function' && superClass !== null) { |
||||||
|
throw new TypeError('Super expression must either be null or a function') |
||||||
|
} |
||||||
|
subClass.prototype = Object.create(superClass && superClass.prototype, { |
||||||
|
constructor: { |
||||||
|
value: subClass, |
||||||
|
writable: true, |
||||||
|
configurable: true, |
||||||
|
}, |
||||||
|
}) |
||||||
|
Object.defineProperty(subClass, 'prototype', { |
||||||
|
writable: false, |
||||||
|
}) |
||||||
|
if (superClass) _setPrototypeOf(subClass, superClass) |
||||||
|
} |
||||||
|
function _getPrototypeOf(o) { |
||||||
|
_getPrototypeOf = Object.setPrototypeOf |
||||||
|
? Object.getPrototypeOf.bind() |
||||||
|
: function _getPrototypeOf(o) { |
||||||
|
return o.__proto__ || Object.getPrototypeOf(o) |
||||||
|
} |
||||||
|
return _getPrototypeOf(o) |
||||||
|
} |
||||||
|
function _setPrototypeOf(o, p) { |
||||||
|
_setPrototypeOf = Object.setPrototypeOf |
||||||
|
? Object.setPrototypeOf.bind() |
||||||
|
: function _setPrototypeOf(o, p) { |
||||||
|
o.__proto__ = p |
||||||
|
return o |
||||||
|
} |
||||||
|
return _setPrototypeOf(o, p) |
||||||
|
} |
||||||
|
function _assertThisInitialized(self) { |
||||||
|
if (self === void 0) { |
||||||
|
throw new ReferenceError( |
||||||
|
"this hasn't been initialised - super() hasn't been called", |
||||||
|
) |
||||||
|
} |
||||||
|
return self |
||||||
|
} |
||||||
|
function _possibleConstructorReturn(self, call) { |
||||||
|
if (call && (typeof call === 'object' || typeof call === 'function')) { |
||||||
|
return call |
||||||
|
} else if (call !== void 0) { |
||||||
|
throw new TypeError( |
||||||
|
'Derived constructors may only return object or undefined', |
||||||
|
) |
||||||
|
} |
||||||
|
return _assertThisInitialized(self) |
||||||
|
} |
||||||
|
function _slicedToArray(arr, i) { |
||||||
|
return ( |
||||||
|
_arrayWithHoles(arr) || |
||||||
|
_iterableToArrayLimit(arr, i) || |
||||||
|
_unsupportedIterableToArray(arr, i) || |
||||||
|
_nonIterableRest() |
||||||
|
) |
||||||
|
} |
||||||
|
function _toConsumableArray(arr) { |
||||||
|
return ( |
||||||
|
_arrayWithoutHoles(arr) || |
||||||
|
_iterableToArray(arr) || |
||||||
|
_unsupportedIterableToArray(arr) || |
||||||
|
_nonIterableSpread() |
||||||
|
) |
||||||
|
} |
||||||
|
function _arrayWithoutHoles(arr) { |
||||||
|
if (Array.isArray(arr)) return _arrayLikeToArray(arr) |
||||||
|
} |
||||||
|
function _arrayWithHoles(arr) { |
||||||
|
if (Array.isArray(arr)) return arr |
||||||
|
} |
||||||
|
function _iterableToArray(iter) { |
||||||
|
if ( |
||||||
|
(typeof Symbol !== 'undefined' && iter[Symbol.iterator] != null) || |
||||||
|
iter['@@iterator'] != null |
||||||
|
) |
||||||
|
return Array.from(iter) |
||||||
|
} |
||||||
|
function _unsupportedIterableToArray(o, minLen) { |
||||||
|
if (!o) return |
||||||
|
if (typeof o === 'string') return _arrayLikeToArray(o, minLen) |
||||||
|
let n = Object.prototype.toString.call(o).slice(8, -1) |
||||||
|
if (n === 'Object' && o.constructor) n = o.constructor.name |
||||||
|
if (n === 'Map' || n === 'Set') return Array.from(o) |
||||||
|
if (n === 'Arguments' || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) |
||||||
|
return _arrayLikeToArray(o, minLen) |
||||||
|
} |
||||||
|
function _arrayLikeToArray(arr, len) { |
||||||
|
if (len == null || len > arr.length) len = arr.length |
||||||
|
for (let i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i] |
||||||
|
return arr2 |
||||||
|
} |
||||||
|
function _nonIterableSpread() { |
||||||
|
throw new TypeError( |
||||||
|
'Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.', |
||||||
|
) |
||||||
|
} |
||||||
|
function _nonIterableRest() { |
||||||
|
throw new TypeError( |
||||||
|
'Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.', |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
let three = |
||||||
|
typeof window !== 'undefined' && window.THREE |
||||||
|
? window.THREE // Prefer consumption from global THREE, if exists
|
||||||
|
: { |
||||||
|
LinearFilter: LinearFilter, |
||||||
|
Sprite: Sprite, |
||||||
|
SpriteMaterial: SpriteMaterial, |
||||||
|
SRGBColorSpace: SRGBColorSpace, |
||||||
|
Texture: Texture, |
||||||
|
} |
||||||
|
let _default = /*#__PURE__*/ (function (_three$Sprite) { |
||||||
|
_inherits(_default, _three$Sprite) |
||||||
|
function _default() { |
||||||
|
let _this |
||||||
|
let text = |
||||||
|
arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '' |
||||||
|
let textHeight = |
||||||
|
arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 10 |
||||||
|
let color = |
||||||
|
arguments.length > 2 && arguments[2] !== undefined |
||||||
|
? arguments[2] |
||||||
|
: 'rgba(255, 255, 255, 1)' |
||||||
|
_classCallCheck(this, _default) |
||||||
|
_this = _callSuper(this, _default, [new three.SpriteMaterial()]) |
||||||
|
_this._text = ''.concat(text) |
||||||
|
_this._textHeight = textHeight |
||||||
|
_this._color = color |
||||||
|
_this._backgroundColor = false // no background color
|
||||||
|
|
||||||
|
_this._padding = 0 |
||||||
|
_this._borderWidth = 0 |
||||||
|
_this._borderRadius = 0 |
||||||
|
_this._borderColor = 'white' |
||||||
|
_this._strokeWidth = 0 |
||||||
|
_this._strokeColor = 'white' |
||||||
|
_this._fontFace = 'system-ui' |
||||||
|
_this._fontSize = 90 // defines text resolution
|
||||||
|
_this._fontWeight = 'normal' |
||||||
|
_this._canvas = document.createElement('canvas') |
||||||
|
_this._genCanvas() |
||||||
|
return _this |
||||||
|
} |
||||||
|
_createClass(_default, [ |
||||||
|
{ |
||||||
|
key: 'text', |
||||||
|
get: function get() { |
||||||
|
return this._text |
||||||
|
}, |
||||||
|
set: function set(text) { |
||||||
|
this._text = text |
||||||
|
this._genCanvas() |
||||||
|
}, |
||||||
|
}, |
||||||
|
{ |
||||||
|
key: 'textHeight', |
||||||
|
get: function get() { |
||||||
|
return this._textHeight |
||||||
|
}, |
||||||
|
set: function set(textHeight) { |
||||||
|
this._textHeight = textHeight |
||||||
|
this._genCanvas() |
||||||
|
}, |
||||||
|
}, |
||||||
|
{ |
||||||
|
key: 'color', |
||||||
|
get: function get() { |
||||||
|
return this._color |
||||||
|
}, |
||||||
|
set: function set(color) { |
||||||
|
this._color = color |
||||||
|
this._genCanvas() |
||||||
|
}, |
||||||
|
}, |
||||||
|
{ |
||||||
|
key: 'backgroundColor', |
||||||
|
get: function get() { |
||||||
|
return this._backgroundColor |
||||||
|
}, |
||||||
|
set: function set(color) { |
||||||
|
this._backgroundColor = color |
||||||
|
this._genCanvas() |
||||||
|
}, |
||||||
|
}, |
||||||
|
{ |
||||||
|
key: 'padding', |
||||||
|
get: function get() { |
||||||
|
return this._padding |
||||||
|
}, |
||||||
|
set: function set(padding) { |
||||||
|
this._padding = padding |
||||||
|
this._genCanvas() |
||||||
|
}, |
||||||
|
}, |
||||||
|
{ |
||||||
|
key: 'borderWidth', |
||||||
|
get: function get() { |
||||||
|
return this._borderWidth |
||||||
|
}, |
||||||
|
set: function set(borderWidth) { |
||||||
|
this._borderWidth = borderWidth |
||||||
|
this._genCanvas() |
||||||
|
}, |
||||||
|
}, |
||||||
|
{ |
||||||
|
key: 'borderRadius', |
||||||
|
get: function get() { |
||||||
|
return this._borderRadius |
||||||
|
}, |
||||||
|
set: function set(borderRadius) { |
||||||
|
this._borderRadius = borderRadius |
||||||
|
this._genCanvas() |
||||||
|
}, |
||||||
|
}, |
||||||
|
{ |
||||||
|
key: 'borderColor', |
||||||
|
get: function get() { |
||||||
|
return this._borderColor |
||||||
|
}, |
||||||
|
set: function set(borderColor) { |
||||||
|
this._borderColor = borderColor |
||||||
|
this._genCanvas() |
||||||
|
}, |
||||||
|
}, |
||||||
|
{ |
||||||
|
key: 'fontFace', |
||||||
|
get: function get() { |
||||||
|
return this._fontFace |
||||||
|
}, |
||||||
|
set: function set(fontFace) { |
||||||
|
this._fontFace = fontFace |
||||||
|
this._genCanvas() |
||||||
|
}, |
||||||
|
}, |
||||||
|
{ |
||||||
|
key: 'fontSize', |
||||||
|
get: function get() { |
||||||
|
return this._fontSize |
||||||
|
}, |
||||||
|
set: function set(fontSize) { |
||||||
|
this._fontSize = fontSize |
||||||
|
this._genCanvas() |
||||||
|
}, |
||||||
|
}, |
||||||
|
{ |
||||||
|
key: 'fontWeight', |
||||||
|
get: function get() { |
||||||
|
return this._fontWeight |
||||||
|
}, |
||||||
|
set: function set(fontWeight) { |
||||||
|
this._fontWeight = fontWeight |
||||||
|
this._genCanvas() |
||||||
|
}, |
||||||
|
}, |
||||||
|
{ |
||||||
|
key: 'strokeWidth', |
||||||
|
get: function get() { |
||||||
|
return this._strokeWidth |
||||||
|
}, |
||||||
|
set: function set(strokeWidth) { |
||||||
|
this._strokeWidth = strokeWidth |
||||||
|
this._genCanvas() |
||||||
|
}, |
||||||
|
}, |
||||||
|
{ |
||||||
|
key: 'strokeColor', |
||||||
|
get: function get() { |
||||||
|
return this._strokeColor |
||||||
|
}, |
||||||
|
set: function set(strokeColor) { |
||||||
|
this._strokeColor = strokeColor |
||||||
|
this._genCanvas() |
||||||
|
}, |
||||||
|
}, |
||||||
|
{ |
||||||
|
key: '_genCanvas', |
||||||
|
value: function _genCanvas() { |
||||||
|
let _this2 = this |
||||||
|
let canvas = this._canvas |
||||||
|
let ctx = canvas.getContext('2d') |
||||||
|
let border = Array.isArray(this.borderWidth) |
||||||
|
? this.borderWidth |
||||||
|
: [this.borderWidth, this.borderWidth] // x,y border
|
||||||
|
let relBorder = border.map(function (b) { |
||||||
|
return b * _this2.fontSize * 0.1 |
||||||
|
}) // border in canvas units
|
||||||
|
|
||||||
|
let borderRadius = Array.isArray(this.borderRadius) |
||||||
|
? this.borderRadius |
||||||
|
: [ |
||||||
|
this.borderRadius, |
||||||
|
this.borderRadius, |
||||||
|
this.borderRadius, |
||||||
|
this.borderRadius, |
||||||
|
] // tl tr br bl corners
|
||||||
|
let relBorderRadius = borderRadius.map(function (b) { |
||||||
|
return b * _this2.fontSize * 0.1 |
||||||
|
}) // border radius in canvas units
|
||||||
|
|
||||||
|
let padding = Array.isArray(this.padding) |
||||||
|
? this.padding |
||||||
|
: [this.padding, this.padding] // x,y padding
|
||||||
|
let relPadding = padding.map(function (p) { |
||||||
|
return p * _this2.fontSize * 0.1 |
||||||
|
}) // padding in canvas units
|
||||||
|
|
||||||
|
let lines = this.text.split('\n') |
||||||
|
let font = '' |
||||||
|
.concat(this.fontWeight, ' ') |
||||||
|
.concat(this.fontSize, 'px ') |
||||||
|
.concat(this.fontFace) |
||||||
|
ctx.font = font // measure canvas with appropriate font
|
||||||
|
let innerWidth = Math.max.apply( |
||||||
|
Math, |
||||||
|
_toConsumableArray( |
||||||
|
lines.map(function (line) { |
||||||
|
return ctx.measureText(line).width |
||||||
|
}), |
||||||
|
), |
||||||
|
) |
||||||
|
let innerHeight = this.fontSize * lines.length |
||||||
|
canvas.width = innerWidth + relBorder[0] * 2 + relPadding[0] * 2 |
||||||
|
canvas.height = innerHeight + relBorder[1] * 2 + relPadding[1] * 2 |
||||||
|
|
||||||
|
// paint border
|
||||||
|
if (this.borderWidth) { |
||||||
|
ctx.strokeStyle = this.borderColor |
||||||
|
if (relBorder[0]) { |
||||||
|
// left + right borders
|
||||||
|
let hb = relBorder[0] / 2 |
||||||
|
ctx.lineWidth = relBorder[0] |
||||||
|
ctx.beginPath() |
||||||
|
ctx.moveTo(hb, relBorderRadius[0]) |
||||||
|
ctx.lineTo(hb, canvas.height - relBorderRadius[3]) |
||||||
|
ctx.moveTo(canvas.width - hb, relBorderRadius[1]) |
||||||
|
ctx.lineTo(canvas.width - hb, canvas.height - relBorderRadius[2]) |
||||||
|
ctx.stroke() |
||||||
|
} |
||||||
|
if (relBorder[1]) { |
||||||
|
// top + bottom borders
|
||||||
|
let _hb = relBorder[1] / 2 |
||||||
|
ctx.lineWidth = relBorder[1] |
||||||
|
ctx.beginPath() |
||||||
|
ctx.moveTo(Math.max(relBorder[0], relBorderRadius[0]), _hb) |
||||||
|
ctx.lineTo( |
||||||
|
canvas.width - Math.max(relBorder[0], relBorderRadius[1]), |
||||||
|
_hb, |
||||||
|
) |
||||||
|
ctx.moveTo( |
||||||
|
Math.max(relBorder[0], relBorderRadius[3]), |
||||||
|
canvas.height - _hb, |
||||||
|
) |
||||||
|
ctx.lineTo( |
||||||
|
canvas.width - Math.max(relBorder[0], relBorderRadius[2]), |
||||||
|
canvas.height - _hb, |
||||||
|
) |
||||||
|
ctx.stroke() |
||||||
|
} |
||||||
|
if (this.borderRadius) { |
||||||
|
// strike rounded corners
|
||||||
|
let cornerWidth = Math.max.apply( |
||||||
|
Math, |
||||||
|
_toConsumableArray(relBorder), |
||||||
|
) |
||||||
|
let _hb2 = cornerWidth / 2 |
||||||
|
ctx.lineWidth = cornerWidth |
||||||
|
ctx.beginPath() |
||||||
|
;[ |
||||||
|
!!relBorderRadius[0] && [ |
||||||
|
relBorderRadius[0], |
||||||
|
_hb2, |
||||||
|
_hb2, |
||||||
|
relBorderRadius[0], |
||||||
|
], |
||||||
|
!!relBorderRadius[1] && [ |
||||||
|
canvas.width - relBorderRadius[1], |
||||||
|
canvas.width - _hb2, |
||||||
|
_hb2, |
||||||
|
relBorderRadius[1], |
||||||
|
], |
||||||
|
!!relBorderRadius[2] && [ |
||||||
|
canvas.width - relBorderRadius[2], |
||||||
|
canvas.width - _hb2, |
||||||
|
canvas.height - _hb2, |
||||||
|
canvas.height - relBorderRadius[2], |
||||||
|
], |
||||||
|
!!relBorderRadius[3] && [ |
||||||
|
relBorderRadius[3], |
||||||
|
_hb2, |
||||||
|
canvas.height - _hb2, |
||||||
|
canvas.height - relBorderRadius[3], |
||||||
|
], |
||||||
|
] |
||||||
|
.filter(function (d) { |
||||||
|
return d |
||||||
|
}) |
||||||
|
.forEach(function (_ref) { |
||||||
|
let _ref2 = _slicedToArray(_ref, 4), |
||||||
|
x0 = _ref2[0], |
||||||
|
x1 = _ref2[1], |
||||||
|
y0 = _ref2[2], |
||||||
|
y1 = _ref2[3] |
||||||
|
ctx.moveTo(x0, y0) |
||||||
|
ctx.quadraticCurveTo(x1, y0, x1, y1) |
||||||
|
}) |
||||||
|
ctx.stroke() |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// paint background
|
||||||
|
if (this.backgroundColor) { |
||||||
|
ctx.fillStyle = this.backgroundColor |
||||||
|
if (!this.borderRadius) { |
||||||
|
ctx.fillRect( |
||||||
|
relBorder[0], |
||||||
|
relBorder[1], |
||||||
|
canvas.width - relBorder[0] * 2, |
||||||
|
canvas.height - relBorder[1] * 2, |
||||||
|
) |
||||||
|
} else { |
||||||
|
// fill with rounded corners
|
||||||
|
ctx.beginPath() |
||||||
|
ctx.moveTo(relBorder[0], relBorderRadius[0]) |
||||||
|
;[ |
||||||
|
[ |
||||||
|
relBorder[0], |
||||||
|
relBorderRadius[0], |
||||||
|
canvas.width - relBorderRadius[1], |
||||||
|
relBorder[1], |
||||||
|
relBorder[1], |
||||||
|
relBorder[1], |
||||||
|
], |
||||||
|
// t
|
||||||
|
[ |
||||||
|
canvas.width - relBorder[0], |
||||||
|
canvas.width - relBorder[0], |
||||||
|
canvas.width - relBorder[0], |
||||||
|
relBorder[1], |
||||||
|
relBorderRadius[1], |
||||||
|
canvas.height - relBorderRadius[2], |
||||||
|
], |
||||||
|
// r
|
||||||
|
[ |
||||||
|
canvas.width - relBorder[0], |
||||||
|
canvas.width - relBorderRadius[2], |
||||||
|
relBorderRadius[3], |
||||||
|
canvas.height - relBorder[1], |
||||||
|
canvas.height - relBorder[1], |
||||||
|
canvas.height - relBorder[1], |
||||||
|
], |
||||||
|
// b
|
||||||
|
[ |
||||||
|
relBorder[0], |
||||||
|
relBorder[0], |
||||||
|
relBorder[0], |
||||||
|
canvas.height - relBorder[1], |
||||||
|
canvas.height - relBorderRadius[3], |
||||||
|
relBorderRadius[0], |
||||||
|
], // t
|
||||||
|
].forEach(function (_ref3) { |
||||||
|
let _ref4 = _slicedToArray(_ref3, 6), |
||||||
|
x0 = _ref4[0], |
||||||
|
x1 = _ref4[1], |
||||||
|
x2 = _ref4[2], |
||||||
|
y0 = _ref4[3], |
||||||
|
y1 = _ref4[4], |
||||||
|
y2 = _ref4[5] |
||||||
|
ctx.quadraticCurveTo(x0, y0, x1, y1) |
||||||
|
ctx.lineTo(x2, y2) |
||||||
|
}) |
||||||
|
ctx.closePath() |
||||||
|
ctx.fill() |
||||||
|
} |
||||||
|
} |
||||||
|
ctx.translate.apply(ctx, _toConsumableArray(relBorder)) |
||||||
|
ctx.translate.apply(ctx, _toConsumableArray(relPadding)) |
||||||
|
|
||||||
|
// paint text
|
||||||
|
ctx.font = font // Set font again after canvas is resized, as context properties are reset
|
||||||
|
ctx.fillStyle = this.color |
||||||
|
ctx.textBaseline = 'bottom' |
||||||
|
let drawTextStroke = this.strokeWidth > 0 |
||||||
|
if (drawTextStroke) { |
||||||
|
ctx.lineWidth = (this.strokeWidth * this.fontSize) / 10 |
||||||
|
ctx.strokeStyle = this.strokeColor |
||||||
|
} |
||||||
|
lines.forEach(function (line, index) { |
||||||
|
let lineX = (innerWidth - ctx.measureText(line).width) / 2 |
||||||
|
let lineY = (index + 1) * _this2.fontSize |
||||||
|
drawTextStroke && ctx.strokeText(line, lineX, lineY) |
||||||
|
ctx.fillText(line, lineX, lineY) |
||||||
|
}) |
||||||
|
|
||||||
|
// Inject canvas into sprite
|
||||||
|
if (this.material.map) this.material.map.dispose() // gc previous texture
|
||||||
|
let texture = (this.material.map = new three.Texture(canvas)) |
||||||
|
texture.minFilter = three.LinearFilter |
||||||
|
texture.colorSpace = three.SRGBColorSpace |
||||||
|
texture.needsUpdate = true |
||||||
|
let yScale = |
||||||
|
this.textHeight * lines.length + border[1] * 2 + padding[1] * 2 |
||||||
|
this.scale.set((yScale * canvas.width) / canvas.height, yScale, 0) |
||||||
|
}, |
||||||
|
}, |
||||||
|
{ |
||||||
|
key: 'clone', |
||||||
|
value: function clone() { |
||||||
|
return new this.constructor( |
||||||
|
this.text, |
||||||
|
this.textHeight, |
||||||
|
this.color, |
||||||
|
).copy(this) |
||||||
|
}, |
||||||
|
}, |
||||||
|
{ |
||||||
|
key: 'copy', |
||||||
|
value: function copy(source) { |
||||||
|
three.Sprite.prototype.copy.call(this, source) |
||||||
|
this.color = source.color |
||||||
|
this.backgroundColor = source.backgroundColor |
||||||
|
this.padding = source.padding |
||||||
|
this.borderWidth = source.borderWidth |
||||||
|
this.borderColor = source.borderColor |
||||||
|
this.fontFace = source.fontFace |
||||||
|
this.fontSize = source.fontSize |
||||||
|
this.fontWeight = source.fontWeight |
||||||
|
this.strokeWidth = source.strokeWidth |
||||||
|
this.strokeColor = source.strokeColor |
||||||
|
return this |
||||||
|
}, |
||||||
|
}, |
||||||
|
]) |
||||||
|
return _default |
||||||
|
})(three.Sprite) |
||||||
|
|
||||||
|
export { _default as default } |
Loading…
Reference in new issue