Skip to content

Instantly share code, notes, and snippets.

@wintercn
Last active November 27, 2019 16:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save wintercn/5b95335dc3681588b71ce435b2400995 to your computer and use it in GitHub Desktop.
Save wintercn/5b95335dc3681588b71ce435b2400995 to your computer and use it in GitHub Desktop.
<body style="margin:0;">
<div id="app" style="position:relative;width:100%;height:100%;">
</div>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<script>
Vue.component('local-storage', {
props: ['value', 'key'],
template: `<div></div>`,
mounted(){
if(!localStorage[this.$props.key])
return;
var str = JSON.stringify(this.$props.value);
if(str != localStorage[this.$props.key])
this.$emit('input', JSON.parse(localStorage[this.$props.key]))
},
watch: {
value: {
deep: true,
handler(newVal, oldVal) { // watch it
console.log(newVal);
if(!this.updater) {
this.updater = () => {
console.log(this.$props.key);
localStorage[this.$props.key] = JSON.stringify(this.$props.value);
this.updater = null;
}
setTimeout(() => this.updater(), 1000);
}
}
}
}
})
Vue.component('mouse', {
props: ['value'],
template: `<div></div>`,
mounted(){
document.addEventListener("mousemove", event => {
this.$emit('input', {
x: event.clientX,
y: event.clientY
})
})
}
})
Vue.component('dragable', {
props: ['value'],
template: `
<div style="position:absolute;overflow:visible;"
v-bind:style="{ top: value.y, left: value.x }"
v-on:mousedown="start"
onselectstart="event.preventDefault();return false;"
><slot></slot></div>`,
methods: {
start: function (event) {
this.startX = event.clientX;
this.startY = event.clientY;
this.startValue = { ...this.value };
this.dragging = false;
var move = event => {
if (Math.abs(event.clientX - this.startX) > 3 ||
Math.abs(event.clientY - this.startY) > 3)
this.dragging = true;
if (this.dragging) {
this.$emit('input', {
x: this.startValue.x + event.clientX - this.startX,
y: this.startValue.y + event.clientY - this.startY
})
}
}
var end = event => {
document.removeEventListener('mousemove', move, false);
document.removeEventListener('mouseup', end, false);
this.dragging = false;
}
document.addEventListener('mousemove', move, false);
document.addEventListener('mouseup', end, false);
}
}
})
var component = new Vue({
template: `
<div v-on:contextmenu="clearSelect($event)" style="height:100%" v-bind:style="{width:width}">
<svg style="position:relative;overflow:visible;">
<polyline v-for="(line) in map.lines" v-bind:points="map.nodes[line.from].x + ',' + map.nodes[line.from].y + ' ' + map.nodes[line.to].x + ',' + map.nodes[line.to].y "
style="stroke:#ccc;stroke-width:2"/>
<polyline v-if="selected.index !== null" v-bind:points="map.nodes[selected.index].x + ',' + map.nodes[selected.index].y + ' ' + mouse.x + ',' + mouse.y "
style="stroke:#ccc;stroke-width:2"/>
</svg>
<dragable v-for="(node, i) in map.nodes" v-model="map.nodes[i]" v-bind:style="{border:selected.index == i ? 'solid 1px green' : ''}" style="transform:translate(-50%, -50%);position:absolute;width:100px;height:30px;background-color:grey;">
<div style="width:100%;height:100%;" v-bind:data-i="i" v-on:click="select($event)"></div>
</dragable>
<button v-on:click="add">加</button>
<mouse v-model="mouse" />
<local-storage v-model="map" key="map"></local-storage>
</div>
`,
data: {
map: {
nodes: [{ x: 200, y: 200 }, { x: 400, y: 400 }],
lines: [ {from:0, to:1} ]
},
selected: {
index: null,
x:0,
y:0
},
mouse: {
x: 0,
y: 0
},
width: 1000,
},
methods: {
add(){
this.$data.width += 300
this.$data.map.nodes.push({x:this.$data.map.nodes[this.$data.map.nodes.length-1].x + 300,y:400})
},
select(event){
if(this.$data.selected.index === null)
this.$data.selected.index = event.target.dataset["i"];
else {
this.$data.map.lines.push({
from: this.$data.selected.index,
to: event.target.dataset["i"]
})
this.$data.selected.index = null;
}
},
clearSelect(event){
event.preventDefault();
this.$data.selected.index = null;
}
}
}).$mount();
document.getElementById('app').appendChild(component.$el)
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment