-
-
Save DCdafan/67c2bc70f389ee4f7d7041c0970f3f85 to your computer and use it in GitHub Desktop.
vue+svg 实现缩放
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<template> | |
<svg width="800px" height="800px" version="1.1" | |
xmlns="http://www.w3.org/2000/svg" viewBox="0 0 800 800"> | |
<g class="port_output" style="pointer-events: all;"> | |
<rect fill="#fff" stroke-width="1.5" | |
:x="selectedItem.x" :y="selectedItem.y" | |
:width="selectedItem.width" :height="selectedItem.height" | |
:transform="transform" | |
style="vector-effect: non-scaling-stroke" | |
class="port" @click="pointClick" stroke-dasharray="none" stroke="#000"></rect> | |
<!--<rect x="200" y="200" width="100" height="100" class="port" @click="pointClick"></rect>--> | |
<!--<rect x="400" y="200" width="100" transform="scale(1.5,1.5)" height="100" class="port" @click="pointClick"></rect>--> | |
</g> | |
<path :d="item" stroke="red" stroke-width="2" fill="none" v-for="(item,index) in listData" | |
:key="index"></path> | |
<path :d="pathPosition" stroke="blue" stroke-width="1" fill="none"></path> | |
<g class="selected"> | |
<circle :cx="itemPosition.cw.value.x" :cy="itemPosition.cw.value.y" r="2.5" | |
stroke="blue" fill="white"></circle> | |
<circle :cx="itemPosition.ce.value.x" :cy="itemPosition.ce.value.y" r="2.5" | |
stroke="blue" fill="white"></circle> | |
<rect style="cursor:nw-resize" | |
:x="itemPosition.nw.value.x - 2.5" :y="itemPosition.nw.value.y - 2.5" | |
stroke="blue" fill="white" | |
width="5" height="5" | |
class="port" | |
@mousedown="shapeScale($event,type='nw')" | |
></rect> | |
<rect style="cursor:ne-resize" | |
:x="itemPosition.ne.value.x - 2.5" :y="itemPosition.ne.value.y - 2.5" | |
stroke="blue" fill="white" | |
width="5" height="5" | |
class="port" | |
@mousedown="shapeScale($event,type='ne')" | |
></rect> | |
<rect style="cursor:sw-resize" | |
:x="itemPosition.sw.value.x - 2.5" :y="itemPosition.sw.value.y - 2.5" | |
stroke="blue" fill="white" | |
width="5" height="5" | |
class="port" | |
@mousedown="shapeScale($event,type='sw')" | |
></rect> | |
<rect style="cursor:se-resize" | |
:x="itemPosition.se.value.x - 2.5" :y="itemPosition.se.value.y - 2.5" | |
stroke="blue" fill="white" | |
width="5" height="5" | |
class="port" | |
@mousedown="shapeScale($event,type='se')" | |
></rect> | |
<rect :x="itemPosition.c.value.x - 2.5" :y="itemPosition.c.value.y - 2.5" | |
stroke="blue" fill="white" | |
width="5" height="5" | |
class="port" | |
@mousedown="shapeScale" | |
></rect> | |
</g> | |
</svg> | |
</template> | |
<script> | |
import * as d3 from 'd3'; | |
export default { | |
name: 'home', | |
data() { | |
return { | |
listData: { | |
'001': 'M1,2L30,40', | |
}, | |
clickPoint: { | |
x: '', | |
y: '' | |
}, | |
itemPosition: { | |
nw: { | |
name: '', | |
value: { | |
x: '', | |
y: '' | |
} | |
}, | |
sw: { | |
name: '', | |
value: { | |
x: '', | |
y: '' | |
} | |
}, | |
ne: { | |
name: '', | |
value: { | |
x: '', | |
y: '' | |
} | |
}, | |
se: { | |
name: '', | |
value: { | |
x: '', | |
y: '' | |
} | |
}, | |
cw: { | |
name: '', | |
value: { | |
x: '0', | |
y: '0' | |
} | |
}, | |
ce: { | |
name: '', | |
value: { | |
x: '0', | |
y: '0' | |
} | |
}, | |
c: { | |
name: '', | |
value: { | |
x: '', | |
y: '' | |
} | |
} | |
}, | |
pathPosition: "", | |
selectedItem: { | |
target:null, | |
width:150, | |
height:150, | |
x:500, | |
y:100, | |
translateX:'', | |
translateY:'' | |
}, | |
scaleValue: { | |
x: 1, | |
y: 1 | |
}, | |
transform:'' | |
} | |
}, | |
computed: { | |
}, | |
mounted() { | |
}, | |
methods: { | |
pointClick(e) { | |
this.selectedItem.target = e.target; | |
this.drawSelectPoint() | |
}, | |
drawSelectPoint(){ | |
const pos = this.selectedItem.target.getBoundingClientRect() | |
// console.log(this.selectedItem.getBBox()) | |
//左上角 | |
this.itemPosition.nw = { | |
name: 'nw', | |
value: { | |
x: pos.left, | |
y: pos.top | |
} | |
} | |
//左下角 | |
this.itemPosition.sw = { | |
name: 'sw', | |
value: { | |
x: pos.left, | |
y: pos.top + pos.height | |
} | |
} | |
//右上角 | |
this.itemPosition.ne = { | |
name: 'ne', | |
value: { | |
x: pos.left + pos.width, | |
y: pos.top | |
} | |
} | |
//右下角 | |
this.itemPosition.se = { | |
name: 'se', | |
value: { | |
x: pos.left + pos.width, | |
y: pos.top + pos.height | |
} | |
} | |
//左中角 | |
this.itemPosition.cw = { | |
name: 'cw', | |
value: { | |
x: pos.left, | |
y: pos.top + (pos.height / 2) | |
} | |
} | |
//右中角 | |
this.itemPosition.ce = { | |
name: 'ce', | |
value: { | |
x: pos.left + pos.width, | |
y: pos.top + (pos.height / 2) | |
} | |
} | |
//中心点 | |
this.itemPosition.c = { | |
name: 'c', | |
value: { | |
x: pos.left + (pos.width / 2), | |
y: pos.top + (pos.height / 2) | |
} | |
} | |
this.drawSelectLine() | |
}, | |
drawSelectLine(){ | |
const path = d3.path() | |
path.moveTo(this.itemPosition.nw.value.x, this.itemPosition.nw.value.y) | |
path.lineTo(this.itemPosition.ne.value.x, this.itemPosition.ne.value.y) | |
path.lineTo(this.itemPosition.se.value.x, this.itemPosition.se.value.y) | |
path.lineTo(this.itemPosition.sw.value.x, this.itemPosition.sw.value.y) | |
path.lineTo(this.itemPosition.nw.value.x, this.itemPosition.nw.value.y) | |
this.pathPosition = path.toString() | |
}, | |
pointDown(e) { | |
this.clickPoint.x = e.offsetX | |
this.clickPoint.y = e.offsetY | |
document.onmousemove = (e) => { | |
this.drawLine(this.clickPoint.x, this.clickPoint.y, e.offsetX, e.offsetY, '002') | |
}; | |
document.onmouseup = () => { | |
document.onmousemove = null; | |
document.onmouseup = null; | |
}; | |
}, | |
drawLine(x1, y1, x2, y2, id) { | |
const path = d3.path() | |
path.moveTo(x1, y1) | |
path.bezierCurveTo(x2, y1, x1, y2, x2, y2); | |
// path.lineTo(x2,y2) | |
this.$set(this.listData, id, path.toString()) | |
console.log(this.listData) | |
}, | |
shapeScale(e,type) { | |
const target = this.selectedItem.target.getBoundingClientRect() | |
this.selectedItem.width = target.width | |
this.selectedItem.height = target.height | |
if(type === 'nw'){ | |
const tx = this.selectedItem.x + this.selectedItem.width | |
const ty = this.selectedItem.y + this.selectedItem.height | |
this.scaleFunc(e,tx,ty,()=>{ | |
this.selectedItem.x = this.selectedItem.translateX - this.selectedItem.width | |
this.selectedItem.y = this.selectedItem.translateY - this.selectedItem.height | |
}) | |
} | |
if(type === 'ne'){ | |
const tx = this.selectedItem.x | |
const ty = this.selectedItem.y + this.selectedItem.height | |
this.scaleFunc(e,tx,ty,()=>{ | |
this.selectedItem.x = this.selectedItem.translateX | |
this.selectedItem.y = this.selectedItem.translateY - this.selectedItem.height | |
}) | |
} | |
if(type === 'sw'){ | |
const tx = this.selectedItem.x + this.selectedItem.width | |
const ty = this.selectedItem.y | |
this.scaleFunc(e,tx,ty,()=>{ | |
this.selectedItem.x = this.selectedItem.translateX - this.selectedItem.width | |
this.selectedItem.y = this.selectedItem.translateY | |
}) | |
} | |
if(type === 'se'){ | |
const tx = this.selectedItem.x | |
const ty = this.selectedItem.y | |
this.scaleFunc(e,tx,ty,()=>{}) | |
} | |
}, | |
scaleFunc(e,tx,ty,upcall){ | |
this.selectedItem.translateX = tx | |
this.selectedItem.translateY = ty | |
const pos_x = e.clientX - this.selectedItem.translateX | |
const pos_y = e.clientY - this.selectedItem.translateY | |
document.onmousemove = (e) => { | |
const move_x = e.clientX - this.selectedItem.translateX | |
const move_y = e.clientY - this.selectedItem.translateY | |
this.scaleValue = { | |
x: move_x / pos_x, | |
y: move_y / pos_y | |
} | |
this.transform = `translate(${this.selectedItem.translateX},${this.selectedItem.translateY}) scale(${this.scaleValue.x},${this.scaleValue.y}) translate(-${this.selectedItem.translateX},-${this.selectedItem.translateY})` | |
this.drawSelectPoint() | |
}; | |
document.onmouseup = () => { | |
document.onmousemove = null; | |
document.onmouseup = null; | |
this.selectedItem.width = this.selectedItem.width * this.scaleValue.x | |
this.selectedItem.height = this.selectedItem.height * this.scaleValue.y | |
this.transform = '' | |
upcall() | |
}; | |
} | |
} | |
} | |
</script> | |
<style> | |
:not(svg), :not(foreignObject) > svg { | |
transform-origin: 0px 0px 0px; | |
} | |
</style> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment