add basic drawing example

This commit is contained in:
Philipp Kühn
2020-12-05 20:56:12 +01:00
parent 29d076c4c4
commit 3157e7f763
7 changed files with 505 additions and 6 deletions

View File

@@ -0,0 +1,150 @@
<template>
<node-view-wrapper class="draw">
<button @click="clear">
clear
</button>
<svg viewBox="0 0 500 250" ref="canvas">
<template v-for="line in node.attrs.lines">
<path
v-if="line.id !== currentId"
:key="line.id"
:d="line.d"
:id="`id-${line.id}`"
/>
</template>
</svg>
</node-view-wrapper>
</template>
<script>
import { v4 as uuid } from 'uuid'
import * as d3 from 'd3'
export default {
props: {
updateAttributes: {
type: Function,
required: true,
},
node: {
type: Object,
required: true,
},
},
data() {
return {
currentId: uuid(),
}
},
methods: {
clear() {
this.updateAttributes({
lines: [],
})
},
},
mounted() {
let ptdata = []
let path
let drawing = false
const line = d3.line()
.x(d => d.x)
.y(d => d.y)
const svg = d3.select(this.$refs.canvas)
const listen = event => {
drawing = true
ptdata = [] // reset point data
path = svg.append('path') // start a new line
.data([ptdata])
.attr('id', `id-${this.currentId}`)
.attr('d', line)
if (event.type === 'mousedown') {
svg.on('mousemove', onmove)
} else {
svg.on('touchmove', onmove)
}
}
const ignore = event => {
svg.on('mousemove', null)
svg.on('touchmove', null)
if (!drawing) {
return
}
drawing = false
d3.select(this.$refs.canvas).select(`#id-${this.currentId}`).remove()
this.currentId = uuid()
}
svg
.on('mousedown', listen)
.on('touchstart', listen)
.on('touchend', ignore)
.on('touchleave', ignore)
.on('mouseup', ignore)
.on('mouseleave', ignore)
// ignore default touch behavior
const touchEvents = ['touchstart', 'touchmove', 'touchend']
touchEvents.forEach(eventName => {
document.body.addEventListener(eventName, e => {
e.preventDefault()
})
})
function onmove(event) {
const point = d3.pointer(event)
// push a new data point onto the back
ptdata.push({ x: point[0], y: point[1] })
tick()
}
const tick = () => {
path.attr('d', points => {
const d = line(points)
const lines = this.node.attrs.lines.filter(item => item.id !== this.currentId)
this.updateAttributes({
lines: [
...lines,
{
id: this.currentId,
d,
},
],
})
return d
})
}
},
}
</script>
<style lang="scss">
.draw {
svg {
background: #EEE;
cursor: crosshair;
}
path {
fill: none;
stroke: #000;
stroke-width: 2;
}
}
</style>