add CardMap view
This commit is contained in:
@@ -1,12 +1,100 @@
|
|||||||
<template>
|
<template>
|
||||||
<component-debug :component="this" />
|
<b-overlay :show="loading" class="h-100">
|
||||||
|
<svg
|
||||||
|
width="100%" height="100%"
|
||||||
|
ref="svg" id="vis"
|
||||||
|
v-if="textsDepart"
|
||||||
|
:view-box.camel="viewBox"
|
||||||
|
>
|
||||||
|
<g id="cards">
|
||||||
|
<foreignObject
|
||||||
|
v-for="(node, i) in nodes" :key="i"
|
||||||
|
width="500" height="300"
|
||||||
|
:x="node.x" :y="node.y"
|
||||||
|
:transform="`rotate(${node.rotate})`"
|
||||||
|
>
|
||||||
|
<text-mini-card
|
||||||
|
:id="textsDepart[i].id"
|
||||||
|
:text-data="textsDepart[i]"
|
||||||
|
/>
|
||||||
|
</foreignObject>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
</b-overlay>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import { mapGetters } from 'vuex'
|
||||||
|
|
||||||
|
import { select, randomUniform, zoom } from 'd3'
|
||||||
|
import {
|
||||||
|
forceSimulation, forceCenter, forceCollide
|
||||||
|
} from 'd3-force'
|
||||||
|
|
||||||
|
|
||||||
|
import TextMiniCard from '@/components/text/TextMiniCard'
|
||||||
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'CardMap'
|
name: 'CardMap',
|
||||||
|
|
||||||
|
components: {
|
||||||
|
TextMiniCard
|
||||||
|
},
|
||||||
|
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
loading: true,
|
||||||
|
width: 100,
|
||||||
|
height: 100,
|
||||||
|
nodes: new Array(20).fill().map((_, i) => ({ x: i, rotate: randomUniform(-25, 25)() })),
|
||||||
|
simulation: forceSimulation(),
|
||||||
|
viewBox: null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
computed: {
|
||||||
|
...mapGetters(['textsDepart'])
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
updateSize () {
|
||||||
|
const { width, height } = this.$refs.svg.getBoundingClientRect()
|
||||||
|
Object.assign(this.$data, { width, height })
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
created () {
|
||||||
|
this.$store.dispatch('GET_TEXTS_DEPART').then(() => {
|
||||||
|
this.loading = false
|
||||||
|
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.updateSize()
|
||||||
|
this.viewBox = `0 0 ${this.width} ${this.height}`
|
||||||
|
const svg = select('#vis')
|
||||||
|
const g = select('#cards')
|
||||||
|
svg.call(zoom()
|
||||||
|
.extent([[0, 0], [this.width, this.height]])
|
||||||
|
.scaleExtent([-5, 8])
|
||||||
|
.on('zoom', zoomed))
|
||||||
|
|
||||||
|
function zoomed ({ transform }) {
|
||||||
|
g.attr('transform', transform)
|
||||||
|
}
|
||||||
|
|
||||||
|
this.simulation
|
||||||
|
.nodes(this.nodes)
|
||||||
|
.force('collide', forceCollide(d => randomUniform(250, 350)()))
|
||||||
|
.force('center', forceCenter(this.width * 0.5, this.height * 0.5))
|
||||||
|
.alphaDecay([0.02])
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
foreignObject {
|
||||||
|
transform-origin: 250, 150;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
Reference in New Issue
Block a user