电子围栏 vue
https://www.matteomattei.com/projects/jpolygon/
1.预览
image.png
2.代码
<template>
<div>
<canvas ref="jPolygon" width="300" height="200" style="cursor:crosshair;" data-imgsrc="https://picsum.photos/400" @mousedown="point_it($event)" oncontextmenu="return false;">
Your browser does not support the HTML5 canvas tag.
</canvas>
<a-button @click="undo()">Undo</a-button>
<a-button @click="clear_canvas()">Clear</a-button>
<textarea ref="coordinates" disabled="disabled" style="width:300px; height:200px;"></textarea>
</div>
</template>
<script>
let ctx = undefined
const pointsArr = [{"x":141,"y":91},{"x":90,"y":124},{"x":183,"y":157},{"x":243,"y":78}]
export default {
name: 'jPolygon',
data () {
return {
perimeter: [],
complete: false,
canvas: null
}
},
mounted () {
this.canvas = this.$refs.jPolygon
this.clear_canvas()
this.init()
},
methods: {
init () {
this.perimeter = pointsArr
},
clear_canvas () {
ctx = undefined
this.perimeter = []
this.complete = false
this.$refs.coordinates.value = ''
this.start(false)
},
start (with_draw) {
const _this = this
let { canvas } = _this
var img = new Image();
img.src = canvas.getAttribute('data-imgsrc')
img.onload = () => {
ctx = canvas.getContext("2d");
ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
if(with_draw == true){
_this.draw(false);
} else {
_this.draw(true);
}
}
},
draw (end) {
let { perimeter, complete } = this
ctx.lineWidth = 2
ctx.strokeStyle = 'yellow'
ctx.lineCap = 'square'
ctx.beginPath()
if (perimeter.length) {
for(var i=0; i<perimeter.length; i++){
if(i==0){
ctx.moveTo(perimeter[i]['x'],perimeter[i]['y']);
end || this.point(perimeter[i]['x'],perimeter[i]['y']);
} else {
ctx.lineTo(perimeter[i]['x'],perimeter[i]['y']);
end || this.point(perimeter[i]['x'],perimeter[i]['y']);
}
}
}
if(end && perimeter.length){
ctx.lineTo(perimeter[0]['x'],perimeter[0]['y']);
ctx.closePath();
ctx.fillStyle = 'rgba(255, 255, 0, 0.2)';
ctx.fill();
ctx.strokeStyle = 'yellow';
complete = true;
}
ctx.stroke();
// print coordinates
if(perimeter.length == 0){
this.$refs.coordinates.value = '';
} else {
this.$refs.coordinates.value = JSON.stringify(perimeter);
}
},
point_it (event) {
let { complete, perimeter, canvas } = this
if(complete){
alert('Polygon already created');
return false;
}
var rect, x, y;
if(event.ctrlKey || event.which === 3 || event.button === 2){
if(perimeter.length==2){
alert('You need at least three points for a polygon');
return false;
}
x = perimeter[0]['x'];
y = perimeter[0]['y'];
if(this.check_intersect(x,y)){
alert('The line you are drowing intersect another line');
return false;
}
this.draw(true);
alert('Polygon closed');
event.preventDefault();
return false;
} else {
rect = canvas.getBoundingClientRect();
x = event.clientX - rect.left;
y = event.clientY - rect.top;
if (perimeter.length>0 && x == perimeter[perimeter.length-1]['x'] && y == perimeter[perimeter.length-1]['y']){
// same point - double click
return false;
}
if(this.check_intersect(x,y)){
alert('The line you are drowing intersect another line');
return false;
}
perimeter.push({'x':x,'y':y});
this.draw(false);
return false;
}
},
check_intersect (x, y) {
let { perimeter } = this
if(perimeter.length < 4){
return false;
}
var p0 = new Array();
var p1 = new Array();
var p2 = new Array();
var p3 = new Array();
p2['x'] = perimeter[perimeter.length-1]['x'];
p2['y'] = perimeter[perimeter.length-1]['y'];
p3['x'] = x;
p3['y'] = y;
for(var i=0; i<perimeter.length-1; i++){
p0['x'] = perimeter[i]['x'];
p0['y'] = perimeter[i]['y'];
p1['x'] = perimeter[i+1]['x'];
p1['y'] = perimeter[i+1]['y'];
if(p1['x'] == p2['x'] && p1['y'] == p2['y']){ continue; }
if(p0['x'] == p3['x'] && p0['y'] == p3['y']){ continue; }
if(this.line_intersects(p0,p1,p2,p3)==true){
return true;
}
}
return false;
},
line_intersects (p0, p1, p2, p3) {
var s1_x, s1_y, s2_x, s2_y;
s1_x = p1['x'] - p0['x'];
s1_y = p1['y'] - p0['y'];
s2_x = p3['x'] - p2['x'];
s2_y = p3['y'] - p2['y'];
var s, t;
s = (-s1_y * (p0['x'] - p2['x']) + s1_x * (p0['y'] - p2['y'])) / (-s2_x * s1_y + s1_x * s2_y);
t = ( s2_x * (p0['y'] - p2['y']) - s2_y * (p0['x'] - p2['x'])) / (-s2_x * s1_y + s1_x * s2_y);
if (s >= 0 && s <= 1 && t >= 0 && t <= 1)
{
// Collision detected
return true;
}
return false; // No collision
},
point (x, y) {
ctx.fillStyle="yellow";
ctx.strokeStyle = 'yellow';
ctx.fillRect(x-2,y-2,4,4);
ctx.moveTo(x,y);
},
undo(){
ctx = undefined;
this.perimeter.pop();
this.complete = false;
this.start(true);
}
}
}
</script>
网友评论