当前位置: 首页 > news >正文

做直播信号网站/成功的营销案例及分析

做直播信号网站,成功的营销案例及分析,建设银行 公户 该网站使用过期的,武汉网站建设有限公司组件 <template><divstyle"display: flex; height: 342px; width: 760px; border: 1px solid #000"><divstyle"position: relative; height: 100%; width: 608px; min-width: 608px"><canvasid"mycanvas"ref"mycanva…

组件

<template><divstyle="display: flex; height: 342px; width: 760px; border: 1px solid #000"><divstyle="position: relative; height: 100%; width: 608px; min-width: 608px"><canvasid="mycanvas"ref="mycanvas":width="canvasWidth":height="canvasHeight"@mousedown="canvasDown($event)"@mousemove="canvasMove($event)"@mouseup="canvasUp($event)"@dblclick="doubleclick()"></canvas></div><divstyle="display: flex;flex-direction: column;padding: 10px;border: 1px solid #cbd2f7;"><el-buttonsize="mini"style="margin-left: 0; margin-top: 10px"@click="beginDraw = !beginDraw":type="beginDraw == false ? 'primary' : ''">{{ beginDraw ? "结束绘制" : "开始绘制" }}</el-button><el-buttonsize="mini"@click="clearAll"style="margin-left: 0; margin-top: 10px">清空绘制区域</el-button><div><el-selectsize="mini"placeholder="请选择绘制类型"v-model="roiType"@change="clearAll"style="margin-top: 10px"><el-option label="区域" value="1" v-if="myRoiType == 1"></el-option><el-option label="线条" value="2" v-if="myRoiType == 2"></el-option><el-optionlabel="单区域+单向单拌线"value="3"v-if="myRoiType == 3"></el-option></el-select><el-selectsize="mini"placeholder="请选择线条方向类型"v-model="directionType"v-show="roiType != '1'":disabled="directionTypeDisabled"style="margin-top: 10px"@change="clearAll"><el-optionv-for="item in directionTypeOptions":key="item.value":label="item.label":value="item.value"></el-option></el-select><div style="display: flex"><el-buttonstyle="width: 50%; margin-top: 10px"size="mini":type="drawType == 1 ? 'primary' : ''"@click="drawType = 1"v-show="roiType == 3">区域</el-button><el-buttonsize="mini":type="drawType == 2 ? 'primary' : ''"@click="drawType = 2"v-show="roiType == 3"style="width: 50%; margin-top: 10px">直线</el-button></div><!-- </el-button-group> --></div><div class="staticLabels"><divclass="staticLabels_item"v-for="(item, index) in allDrawList"@mouseenter="canvasMouseenter(item)"@mouseleave="canvasMouseleave()"v-if="(index >= 0 && !isMultiLine) || (index > 0 && isMultiLine)"><span class="staticLabels_item_span">{{ item.areaName }}</span><iclass="el-icon-close"@click="canvasDeleteOne(item)"style="cursor: pointer"title="删除"></i></div></div></div></div>
</template><script>
export default {props: {canvasKey: {type: String,default: () => "first",},// 画图数据myDrawList: {type: Array,default: () => [],},myRoiType: {type: String,default: () => "1",},},data() {return {isMultiLine: false, //是否多拌线localMyDrawList: [],finalArr: [],roiType: "1",roiTypeOptions: [{value: "1",label: "区域",},{value: "2",label: "线条",},{value: "3",label: "单区域+单向单拌线",},],directionTypeDisabled: false,directionType: "1",directionTypeOptions: [{value: "1",label: "单向单拌线",},{value: "2",label: "双向单拌线",},{value: "3",label: "单向多拌线",},{value: "4",label: "双向多拌线",},],//canvasId: 1,drawType: "1", // 绘制类型 1-多边形 2-线条arrowType: "1", // 箭头类型 1-单向 2-双向all_line_coordinates: [// {//   canvasId: 1,//   areaName: '直线1',//   directionType:1,//   points_coordinates: [{ cor_x: 100, cor_y: 100 }],// }], //所有线条的信息MaxAreaPointsNum: 10, //多边形的最大顶点数MaxLinePointsNum: 5, //线条的最大顶点数MaxAreaNum: 10, //多边形的最大数量MaxLineNum: 10, //线条的最大数量//isdraw: false, //是否在画图形ctx: null, //canvas对象coordinates: [], //当前图形的坐标信息all_coordinates: [// {//   canvasId: 1,//   areaName: '区域1',//   points_coordinates: [{ cor_x: 100, cor_y: 100 }],// },], //所有多边形的信息isdrag: false, //是否拖拽点isdragType: 1, //拖拽类型 1-拖动多边形 2-拖动线条drag_index: [-1, -1], // 拖拽索引beginDraw: false, //开始作画colorList: [// "rgba(88,87,86,.4)",// "rgba(252,230,202,.4)",// "rgba(0,199,140,.4)",// "rgba(227,23,13,.4)",// "rgba(153,51,250,.4)",// "rgba(199,97,20,.4)",// "rgba(250,240,230,.4)",// "rgba(188,143,143,.4)",// "rgba(0,255,0,.4)",// "rgba(244,164,95,.4)",// "rgba(128,42,42,.4)",// "rgba(64,224,205,.4)",// "rgba(237,145,33,.4)",// "rgba(34,139,34,.4)",// "rgba(255,125,64,.4)",// "rgba(107,142,35,.4)",// "rgba(227,207,87,.4)",// "rgba(3,168,158,.4)",// "rgba(255,255,255,.4)",// "rgba(255,255,0,.4)","rgba(16, 128, 219, 0.4)","rgba(16, 128, 219, 0.4)","rgba(16, 128, 219, 0.4)","rgba(16, 128, 219, 0.4)","rgba(16, 128, 219, 0.4)","rgba(16, 128, 219, 0.4)","rgba(16, 128, 219, 0.4)","rgba(16, 128, 219, 0.4)","rgba(16, 128, 219, 0.4)","rgba(16, 128, 219, 0.4)","rgba(16, 128, 219, 0.4)","rgba(16, 128, 219, 0.4)","rgba(16, 128, 219, 0.4)","rgba(16, 128, 219, 0.4)","rgba(16, 128, 219, 0.4)","rgba(16, 128, 219, 0.4)","rgba(16, 128, 219, 0.4)","rgba(16, 128, 219, 0.4)","rgba(16, 128, 219, 0.4)","rgba(16, 128, 219, 0.4)","rgba(255,0,0,.6)", //上色],canvasWidth: 608, //画布宽度canvasHeight: 342, //画布高度//cor_index: 0, //当前多边形的索引 未开发isFirst: true,};},watch: {canvasKey: {handler(val) {this.clearAll();this.showMyDrawList();},deep: true,immediate: true,},myRoiType: {handler(val) {if (val) {this.clearAll();this.roiType = val;//   this.showMyDrawList();}},// deep:true,immediate: true,},// 区域类型:1-区域;2-线条;3-区域+单向线条roiType: {handler(val) {if (val) {this.MaxAreaNum = 10;this.MaxLineNum = 10;this.directionTypeDisabled = false;if (val == 1) {this.drawType = 1;} else if (val == 2) {this.drawType = 2;this.MaxLineNum = 1;}// 3-单区域+单向线条else if (val == 3) {this.MaxAreaNum = 1;this.MaxLineNum = 1;this.arrowType = 1;this.directionType = "1";this.directionTypeDisabled = true;}}this.handleMultiLine();},deep: true,immediate: true,},//线条方向类型:1-单向单拌线,2-双向单拌线,3-单向多拌线,4-双向多拌线directionType: {handler(val) {if (val) {// 1-单向单拌线if (val == 1) {this.arrowType = 1;this.MaxLineNum = 1;}// 2-双向单拌线else if (val == 2) {this.arrowType = 2;this.MaxLineNum = 1;}// 3-单向多拌线else if (val == 3) {this.arrowType = 1;this.MaxLineNum = 2;}// 4-双向多拌线else if (val == 4) {this.arrowType = 2;this.MaxLineNum = 2;}}this.handleMultiLine();},deep: true,// immediate: true,},allDrawList: {handler(val) {// 处理数据-------------------------------------------------var guardAreas = [];val &&val.length > 0 &&val.forEach((item, index) => {var areaName = item.areaName;// 线段if (item.directionType) {var directionType = item.directionType;var linePoints = [];item.points_coordinates &&item.points_coordinates.length > 0 &&item.points_coordinates.forEach((item2, index2) => {linePoints.push({x: (item2.cor_x / this.canvasWidth).toFixed(4),y: (item2.cor_y / this.canvasHeight).toFixed(4),});});var obj = {areaName: areaName,directionType: directionType,linePoints: linePoints,};guardAreas.push(obj);}// 区域else {var directionType = item.directionType;var points = [];item.points_coordinates &&item.points_coordinates.length > 0 &&item.points_coordinates.forEach((item2, index2) => {points.push({x: (item2.cor_x / this.canvasWidth).toFixed(4),y: (item2.cor_y / this.canvasHeight).toFixed(4),});});// 闭合区域 补起点if (points[0].x !== points[points.length - 1].x ||points[0].y !== points[points.length - 1].y) {points.push({x: points[0].x,y: points[0].y,});}var obj = {areaName: areaName,points: points,};guardAreas.push(obj);}});var finalObj = {videoCode: this.canvasKey,guardAreas: guardAreas,};// console.log('回传数据',finalObj);var myDrawList = JSON.parse(JSON.stringify(this.localMyDrawList));var index = myDrawList.findIndex((v) => v.videoCode == finalObj.videoCode);if (index != -1) {myDrawList.splice(index, 1, finalObj);} else {myDrawList.push(finalObj);}// this.$emit("drawListChange", myDrawList);// console.log("数据回传", myDrawList);this.finalArr = [].concat(myDrawList);this.localMyDrawList = [].concat(myDrawList);// 处理数据----------------------------------------------if (val.length == 0) {this.canvasId = 1;}},deep: true,immediate: true,},myDrawList: {handler(val) {this.clearAll();if (val) {this.localMyDrawList = [].concat(val);this.showMyDrawList();}},deep: true,immediate: true,},MaxLineNum: {handler(val) {this.handleMultiLine();},// deep: true,immediate: true,},},computed: {allDrawList: {get() {return this.all_coordinates.concat(this.all_line_coordinates);},},},mounted() {this.initDraw();document.getElementById("mycanvas").oncontextmenu = function (e) {e.preventDefault(); //阻止默认右键菜单};},methods: {handleMultiLine() {if (this.MaxLineNum == 2 && this.roiType == 2) {this.isMultiLine = true;} else {this.isMultiLine = false;}},// 回显showMyDrawList() {var val = this.localMyDrawList || [];if (this.canvasKey) {// console.log("画图回显 localMyDrawList", val);val.forEach((itemOut, index) => {if (itemOut.videoCode == this.canvasKey) {// console.log("当前", itemOut, itemOut.guardAreas);itemOut.guardAreas &&itemOut.guardAreas.length &&itemOut.guardAreas.forEach((item, index) => {// 线段if (item.directionType) {this.directionType = item.directionType;// console.log("回显切换", item.directionType);if (item.directionType == 1 || item.directionType == 3)this.arrowType = 1;else this.arrowType = 2;var areaName = item.areaName;var directionType = item.directionType;var canvasId = Number(item.areaName.substring(2));var points_coordinates = [];item.linePoints.forEach((points, index) => {// 回显的时候不需要最后一个点,因为他跟第一个点重合if (index != 0 &&points.x == item.linePoints[0].x &&points.y == item.linePoints[0].y) {return;}points_coordinates.push({// cor_x: (points.x * this.canvasWidth).toFixed(0),// cor_y: (points.y * this.canvasHeight).toFixed(0),cor_x: Math.ceil(points.x * this.canvasWidth),cor_y: Math.ceil(points.y * this.canvasHeight),});});var obj = {canvasId: canvasId,areaName: areaName,directionType: directionType,points_coordinates: points_coordinates,};this.canvasId = ++canvasId;this.all_line_coordinates.push(obj);}// 区域else {var areaName = item.areaName;var canvasId = Number(item.areaName.substring(2));var points_coordinates = [];item.points.forEach((points, index) => {// 回显的时候不需要最后一个点,因为他跟第一个点重合if (index != 0 &&points.x == item.points[0].x &&points.y == item.points[0].y) {return;}points_coordinates.push({// cor_x: (points.x * this.canvasWidth).toFixed(0),// cor_y: (points.y * this.canvasHeight).toFixed(0),cor_x: Math.ceil(points.x * this.canvasWidth),cor_y: Math.ceil(points.y * this.canvasHeight),});});var obj = {canvasId: canvasId,areaName: areaName,points_coordinates: points_coordinates,};this.canvasId = ++canvasId;this.all_coordinates.push(obj);}});this.$nextTick(() => {// console.log("回显函数");this.drawAll();});}});}},getData() {return this.finalArr;},// 删除一个图形canvasDeleteOne(data) {if (this.isMultiLine) {this.all_line_coordinates = [];this.drawAll();} else {if (data.directionType) {var index = this.all_line_coordinates.findIndex((v) => v.canvasId == data.canvasId);if (index != -1) this.all_line_coordinates.splice(index, 1);} else {var index = this.all_coordinates.findIndex((v) => v.canvasId == data.canvasId);if (index != -1) this.all_coordinates.splice(index, 1);}this.drawAll();}},// 鼠标悬浮,给指定图形上色canvasMouseenter(data) {this.drawAll(data);},// 离开取消上色canvasMouseleave() {this.drawAll();},// 绘制所有图形drawAll(data) {// console.log(this.all_coordinates, this.all_line_coordinates);this.ctx.clearRect(0, 0, this.canvasWidth, this.canvasHeight);if (this.all_coordinates.length != 0 ||this.all_line_coordinates.length != 0) {this.drawlines(data);this.drawcircles();this.fillarea(data);}},// ----------------------------------------------------------// 显示箭头showArrow(x1, y1, x2, y2) {var xm = (x1 + x2) / 2;var ym = (y1 + y2) / 2;var d = 30; //箭头长度 距离if (this.arrowType == 1) {var { x, y } = this.getArrowPoint(x1, y1, x2, y2, d);this.drawArrow(this.ctx, xm, ym, x, y, 30, 10, 1, "#f36");} else {var { x3, y3, x4, y4 } = this.getArrowPoint(x1, y1, x2, y2, d);this.drawArrow(this.ctx, xm, ym, x3, y3, 30, 10, 1, "#f36");this.drawArrow(this.ctx, xm, ym, x4, y4, 30, 10, 1, "#f36");}},// 获取箭头坐标点getArrowPoint(x1, y1, x2, y2, d) {var x0 = (x1 + x2) / 2;var y0 = (y1 + y2) / 2;var k1 = (y2 - y1) / (x2 - x1);var k2 = -1 / k1;var num = Math.sqrt(d ** 2 / (1 + k2 ** 2));var x3 = num + x0;var y3 = k2 * (x3 - x0) + y0;var x4 = 0 - num + x0;var y4 = k2 * (x4 - x0) + y0;// 平行于x轴if (y2 == y1) {x3 = x0;x4 = x0;y3 = y0 + d;y4 = y0 - d;}// 平行于y轴else if (x2 == x1) {x3 = x0 + d;x4 = x0 - d;y3 = y0;y4 = y0;}x3 = Math.floor(x3);y3 = Math.floor(y3);x4 = Math.floor(x4);y4 = Math.floor(y4);var x, y;// 返回向上if (x2 > x1) {y = y3 < y0 ? y3 : y4;x = y == y3 ? x3 : x4;}// 返回向下else {y = y3 < y0 ? y4 : y3;x = y == y3 ? x3 : x4;}if (this.arrowType == 1) {return { x, y };} else {return { x3, y3, x4, y4 };}},// ----------------------------------------------------------/*** @param  dot {{x,y}} 需要判断的点* @param  coordinates {{x,y}[]} 多边形点坐标的数组,为保证图形能够闭合,起点和终点必须相等。*        比如三角形需要四个点表示,第一个点和最后一个点必须相同。*/// 判断点是否点击图形judge(dot, coordinates) {var x = dot.x,y = dot.y;var crossNum = 0;// 点在线段的左侧数目var leftCount = 0;// 点在线段的右侧数目var rightCount = 0;for (var i = 0; i < coordinates.length - 1; i++) {var start = coordinates[i];var end = coordinates[i + 1];// 起点、终点斜率不存在的情况if (start.x === end.x) {// 因为射线向右水平,此处说明不相交if (x > start.x) continue;// 从左侧贯穿if (end.y > start.y && y >= start.y && y <= end.y) {leftCount++;crossNum++;}// 从右侧贯穿if (end.y < start.y && y >= end.y && y <= start.y) {rightCount++;crossNum++;}continue;}// 斜率存在的情况,计算斜率var k = (end.y - start.y) / (end.x - start.x);// 交点的x坐标var x0 = (y - start.y) / k + start.x;// 因为射线向右水平,此处说明不相交if (x > x0) continue;if (end.x > start.x && x0 >= start.x && x0 <= end.x) {crossNum++;if (k >= 0) leftCount++;else rightCount++;}if (end.x < start.x && x0 >= end.x && x0 <= start.x) {crossNum++;if (k >= 0) rightCount++;else leftCount++;}}return leftCount - rightCount !== 0;},// 判断点是否在直线上judgeLine(x1, y1, x2, y2, x, y) {var crossProduct = (x2 - x1) * (y - y1) - (y2 - y1) * (x - x1);// 如果不等于0,说明不共线,直接返回falseif (crossProduct !== 0) {return false;}// 否则,检查c点是否在ab线段的范围内return (Math.min(x1, x2) <= x &&x <= Math.max(x1, x2) &&Math.min(y1, y2) <= y &&y <= Math.max(y1, y2));},initDraw() {//初始化画布对象const canvas = document.querySelector("#mycanvas");this.ctx = canvas.getContext("2d");// this.ctx.strokeStyle = "rgb(0, 195, 155)";this.ctx.strokeStyle = "#f36";},clearAll() {console.log("clearAll");this.all_coordinates = [];this.all_line_coordinates = [];this.coordinates = [];this.isdraw = false;this.canvasId = 1;this.$nextTick(() => {this.ctx &&this.ctx.clearRect(0, 0, this.canvasWidth, this.canvasHeight);});},// 判断是否在拖拽点isdragpoint(x, y) {if (this.all_coordinates.length == 0 &&this.all_line_coordinates.length == 0) {return false;}for (var i = 0; i < this.all_coordinates.length; i++) {for (var j = 0;j < this.all_coordinates[i].points_coordinates.length;j++) {var px = this.all_coordinates[i].points_coordinates[j].cor_x;var py = this.all_coordinates[i].points_coordinates[j].cor_y;//   允许偏移量5if (Math.abs(x - px) <= 5 && Math.abs(y - py) <= 5) {this.drag_index[0] = i;this.drag_index[1] = j;this.isdragType = 1;return true;}}}for (var i = 0; i < this.all_line_coordinates.length; i++) {for (var j = 0;j < this.all_line_coordinates[i].points_coordinates.length;j++) {var px = this.all_line_coordinates[i].points_coordinates[j].cor_x;var py = this.all_line_coordinates[i].points_coordinates[j].cor_y;//   允许偏移量5if (Math.abs(x - px) <= 5 && Math.abs(y - py) <= 5) {this.drag_index[0] = i;this.drag_index[1] = j;this.isdragType = 2;return true;}}}return false;},// 鼠标按下事件canvasDown(e) {var x = e.offsetX;var y = e.offsetY;// 鼠标右键if (e.button == 2) {if (!this.beginDraw) {return;}if (this.coordinates.length) {var last_x = this.coordinates[this.coordinates.length - 1].cor_x;var last_y = this.coordinates[this.coordinates.length - 1].cor_y;if (last_x == x && last_y == y) {// this.$message.error("不能重复点击");// 同一个点 不记录this.doubleclick();return; //同步放开 二选一} else {this.coordinates.push({ cor_x: x, cor_y: y });this.doubleclick();return;}}// 点击顶点if (this.isdragpoint(x, y)) {// 开启弹窗console.log("开启弹窗");if (this.isdragType == 1) {this.all_coordinates.splice(this.drag_index[0], 1);} else {this.all_line_coordinates.splice(this.drag_index[0], 1);}this.drawAll();return;}// 点击图像if (this.all_coordinates.length) {let dot = { x: x, y: y };var flag = false;var arr = JSON.parse(JSON.stringify(this.all_coordinates.map((v) => v.points_coordinates)));for (var i = 0; i < arr.length; i++) {arr[i].push(arr[i][0]);arr[i].forEach((item) => {(item.x = item.cor_x), (item.y = item.cor_y);});if (this.judge(dot, arr[i])) {flag = true;console.log("点击到了多边形上", i);this.all_coordinates.splice(i, 1);this.drawAll();break;}}if (flag) {return;}}// 点击直线 人手很难做到if (this.all_line_coordinates.length) {var flag = false;for (var i = 0; i < this.all_line_coordinates.length; i++) {for (var j = 0;j < this.all_line_coordinates[i].points_coordinates.length - 1;j++) {var x1 = this.all_line_coordinates[i].points_coordinates[j].cor_x;var y1 = this.all_line_coordinates[i].points_coordinates[j].cor_y;var x2 =this.all_line_coordinates[i].points_coordinates[j + 1].cor_x;var y2 =this.all_line_coordinates[i].points_coordinates[j + 1].cor_y;if (this.judgeLine(x1, y1, x2, y2, x, y)) {//判断是否点击到了线上console.log("点击到了线上", i);this.all_line_coordinates.splice(i, 1);this.drawAll();flag = true;break;}}}if (flag) {return;}}}// 鼠标左键else if (e.button == 0) {if (this.isdragpoint(x, y)) {this.isdrag = true; //开启拖拽return;}if (!this.beginDraw) {return;}// 同一个点 不记录if (this.coordinates.length) {var last_x = this.coordinates[this.coordinates.length - 1].cor_x;var last_y = this.coordinates[this.coordinates.length - 1].cor_y;if (last_x == x && last_y == y) {// this.$message.error("不能重复点击");return; //同步放开 二选一}}//获取鼠标按下的坐标,放入数组中if (this.drawType == 1) {if (this.all_coordinates.length == this.MaxAreaNum) {this.$message.error("最多只能画" + this.MaxAreaNum + "个多边形");return;}if (this.coordinates.length + 1 == this.MaxAreaPointsNum) {this.$message.error("多边形最多只能画" + this.MaxAreaPointsNum + "个点");this.coordinates.push({ cor_x: x, cor_y: y });// this.coordinates.push({ cor_x: x, cor_y: y });this.doubleclick();return;}} else if (this.drawType == 2) {if (this.all_line_coordinates.length == this.MaxLineNum) {this.$message.error("最多只能画" + this.MaxLineNum + "条线条");return;}if (this.coordinates.length + 1 == this.MaxLinePointsNum) {this.$message.error("线条最多只能画" + this.MaxLinePointsNum + "个点");this.coordinates.push({ cor_x: x, cor_y: y });// this.coordinates.push({ cor_x: x, cor_y: y });this.doubleclick();return;}}this.coordinates.push({ cor_x: x, cor_y: y });this.isdraw = true; //正在画多边形}},// 鼠标松开事件canvasUp(e) {// if (!this.beginDraw) {//   return;// }if (this.isdrag) {this.isdrag = false; //关闭拖拽点状态}this.drag_index = [-1, -1];this.drawcircle(); //松开画点},//鼠标移动事件canvasMove(e) {//没开始画或者结束画之后不进行操作var x = e.offsetX;var y = e.offsetY;const canvas = document.querySelector("#mycanvas");if (this.isdragpoint(x, y)) {canvas.style.cursor = "pointer";} else {canvas.style.cursor = "default";}if (this.isdrag) {if (this.isdragType == 1) {this.ctx.clearRect(0, 0, this.canvasWidth, this.canvasHeight);this.all_coordinates[this.drag_index[0]].points_coordinates[this.drag_index[1]].cor_x = x;this.all_coordinates[this.drag_index[0]].points_coordinates[this.drag_index[1]].cor_y = y;this.drawlines();this.drawcircles();this.fillarea();} else {this.ctx.clearRect(0, 0, this.canvasWidth, this.canvasHeight);this.all_line_coordinates[this.drag_index[0]].points_coordinates[this.drag_index[1]].cor_x = x;this.all_line_coordinates[this.drag_index[0]].points_coordinates[this.drag_index[1]].cor_y = y;this.drawlines();this.drawcircles();this.fillarea();}}if (!this.beginDraw) {return;}if (this.coordinates.length == 0 || !this.isdraw) {return 0;}this.drawAll();this.drawline(); //把之前的点连线this.drawcircle();//获取上一个点var last_x = this.coordinates[this.coordinates.length - 1].cor_x;var last_y = this.coordinates[this.coordinates.length - 1].cor_y;if (this.drawType == "2") {// 显示箭头this.showArrow(last_x, last_y, x, y);}//获取鼠标移动时的点,画线,实现线段跟踪效果。this.ctx.beginPath();this.ctx.moveTo(last_x, last_y);this.ctx.lineTo(x, y);if (this.drawType == "1") {// 连接起点 更直观var x0 = this.coordinates[0].cor_x;var y0 = this.coordinates[0].cor_y;this.ctx.lineTo(x0, y0);}this.ctx.stroke();this.ctx.closePath();},// 鼠标双击事件doubleclick() {if (!this.beginDraw) {return;}// this.coordinates.pop(); // 同步注释 二选一this.isdraw = false;if (this.drawType == 1) {// 限制图形最少三个点if (this.coordinates.length < 3) {this.$message.error("绘制区域请至少绘制三个点");this.coordinates = [];this.drawAll();return;}this.all_coordinates.push({canvasId: this.canvasId,areaName: "区域" + this.canvasId++,points_coordinates: this.coordinates,});} else {// 限制图形最少两个点if (this.coordinates.length < 2) {this.$message.error("绘制直线请至少绘制两个点");this.coordinates = [];this.drawAll();return;}var name = "";if (this.isMultiLine) {name = "区域1";} else {name = "直线" + this.canvasId++;}this.all_line_coordinates.push({canvasId: this.canvasId,// areaName: "直线" + this.canvasId++,areaName: name,directionType: this.directionType,points_coordinates: this.coordinates,});}this.drawAll();this.ctx.closePath();// console.log(this.coordinates);this.coordinates = [];// 外部调用智能切换if (this.roiType == 3) {if (this.drawType == 1 && this.all_line_coordinates.length == 0) {this.drawType = 2;} else if (this.drawType == 2 && this.all_coordinates.length == 0) {this.drawType = 1;}}if (!this.isMultiLine) this.beginDraw = false;if (this.isMultiLine && this.all_line_coordinates.length == 2)this.beginDraw = false;},rightClick(e) {console.log("右键", e);},drawlines(data) {//把所有多边形画出来for (var i = 0; i < this.all_coordinates.length; i++) {this.ctx.strokeStyle = "#f36";var cors = this.all_coordinates[i].points_coordinates;//前后坐标连线for (var j = 0; j < cors.length - 1; j++) {this.ctx.beginPath();var x0 = cors[j].cor_x;var y0 = cors[j].cor_y;var x1 = cors[j + 1].cor_x;var y1 = cors[j + 1].cor_y;this.ctx.moveTo(x0, y0);this.ctx.lineTo(x1, y1);this.ctx.stroke();this.ctx.closePath();}//最后一个与第一个连线var begin_x = cors[0].cor_x;var begin_y = cors[0].cor_y;var end_x = cors[cors.length - 1].cor_x;var end_y = cors[cors.length - 1].cor_y;this.ctx.beginPath();this.ctx.moveTo(begin_x, begin_y);this.ctx.lineTo(end_x, end_y);this.ctx.stroke();this.ctx.closePath();}//把所有线段画出来for (var i = 0; i < this.all_line_coordinates.length; i++) {this.ctx.strokeStyle = "#f36";// 悬浮上色// this.ctx.strokeStyle = this.colorList[(data.canvasId - 1) % 20];if (data && this.all_line_coordinates[i].canvasId == data.canvasId) {// console.log("线段上色", i, data);// this.ctx.strokeStyle = this.colorList[20];this.ctx.strokeStyle = "white";}// 悬浮上色var cors = this.all_line_coordinates[i].points_coordinates;//前后坐标连线for (var j = 0; j < cors.length - 1; j++) {this.ctx.beginPath();var x0 = cors[j].cor_x;var y0 = cors[j].cor_y;var x1 = cors[j + 1].cor_x;var y1 = cors[j + 1].cor_y;this.showArrow(x0, y0, x1, y1);this.ctx.moveTo(x0, y0);this.ctx.lineTo(x1, y1);this.ctx.stroke();this.ctx.closePath();}}},drawline() {this.ctx.strokeStyle = "#f36";//把当前绘制的多边形之前的坐标线段绘制出来for (var i = 0; i < this.coordinates.length - 1; i++) {this.ctx.beginPath();var x0 = this.coordinates[i].cor_x;var y0 = this.coordinates[i].cor_y;var x1 = this.coordinates[i + 1].cor_x;var y1 = this.coordinates[i + 1].cor_y;if (this.drawType == 2) {this.showArrow(x0, y0, x1, y1);}this.ctx.moveTo(x0, y0);this.ctx.lineTo(x1, y1);this.ctx.stroke();this.ctx.closePath();}},drawcircle() {//为当前的多边形端点画圆this.ctx.fillStyle = "rgb(0, 195, 155)";for (var i = 0; i < this.coordinates.length; i++) {var x = this.coordinates[i].cor_x;var y = this.coordinates[i].cor_y;this.ctx.beginPath();this.ctx.moveTo(x, y);this.ctx.arc(x, y, 5, 0, Math.PI * 2);this.ctx.fill();this.ctx.closePath();}},drawcircles() {//为所有的多边形端点画圆this.ctx.fillStyle = "rgb(0, 195, 155)";for (var i = 0; i < this.all_coordinates.length; i++) {var cors = this.all_coordinates[i].points_coordinates;for (var j = 0; j < cors.length; j++) {var x = cors[j].cor_x;var y = cors[j].cor_y;this.ctx.beginPath();this.ctx.moveTo(x, y);this.ctx.arc(x, y, 5, 0, Math.PI * 2);this.ctx.fill();this.ctx.closePath();}}for (var i = 0; i < this.all_line_coordinates.length; i++) {var cors = this.all_line_coordinates[i].points_coordinates;for (var j = 0; j < cors.length; j++) {var x = cors[j].cor_x;var y = cors[j].cor_y;this.ctx.beginPath();this.ctx.moveTo(x, y);this.ctx.arc(x, y, 5, 0, Math.PI * 2);this.ctx.fill();this.ctx.closePath();}}},fillarea(data) {// this.ctx.fillStyle = "rgba(0, 195, 155,0.4)";for (var i = 0; i < this.all_coordinates.length; i++) {this.ctx.fillStyle = "rgba(16, 128, 219, 0.4)";// 悬浮上色// this.ctx.fillStyle = this.colorList[(data.canvasId - 1) % 20];if (data && this.all_coordinates[i].canvasId == data.canvasId) {this.ctx.fillStyle = this.colorList[20];}// 悬浮上色var cors = this.all_coordinates[i].points_coordinates;var x0 = cors[0].cor_x;var y0 = cors[0].cor_y;this.ctx.beginPath();this.ctx.moveTo(x0, y0);for (var j = 1; j < cors.length; j++) {var x = cors[j].cor_x;var y = cors[j].cor_y;this.ctx.lineTo(x, y);}this.ctx.fill();this.ctx.closePath();}},/*ctx:Canvas绘图环境fromX, fromY:起点坐标(也可以换成p1,只不过它是一个数组)toX, toY:终点坐标 (也可以换成p2,只不过它是一个数组)theta:三角斜边一直线夹角headlen:三角斜边长度width:箭头线宽度color:箭头颜色*/// 绘制箭头drawArrow(ctx, fromX, fromY, toX, toY, theta, headlen, width, color) {theta = typeof theta != "undefined" ? theta : 30;headlen = typeof theta != "undefined" ? headlen : 10;width = typeof width != "undefined" ? width : 1;color = typeof color != "color" ? color : "#000";// 计算各角度和对应的P2,P3坐标var angle = (Math.atan2(fromY - toY, fromX - toX) * 180) / Math.PI,angle1 = ((angle + theta) * Math.PI) / 180,angle2 = ((angle - theta) * Math.PI) / 180,topX = headlen * Math.cos(angle1),topY = headlen * Math.sin(angle1),botX = headlen * Math.cos(angle2),botY = headlen * Math.sin(angle2);// ctx.save();ctx.beginPath();var arrowX = fromX - topX,arrowY = fromY - topY;ctx.moveTo(arrowX, arrowY);ctx.moveTo(fromX, fromY);ctx.lineTo(toX, toY);arrowX = toX + topX;arrowY = toY + topY;ctx.moveTo(arrowX, arrowY);ctx.lineTo(toX, toY);arrowX = toX + botX;arrowY = toY + botY;ctx.lineTo(arrowX, arrowY);// ctx.strokeStyle = color;ctx.lineWidth = width;ctx.stroke();// ctx.restore();},},
};
</script><style lang="scss" scoped>
#mycanvas {/* border: 1px solid red; */// background-color: #2d303b;
}
.staticLabels {flex-grow: 1;overflow: auto;margin-top: 10px;background: rgba(247, 250, 255, 0.8);border-radius: 2px;border: 1px solid #eaecf6;padding-left: 5px;font-size: 12px;line-height: 24px;.staticLabels_item {float: left;height: 24px;background: #ecf3fe;border-radius: 2px;border: 1px solid #2c7be5;padding: 0px 4px;margin-right: 6px;margin-top: 5px;user-select: none;}
}
</style>

使用

<template><div><Canvasref="drawArea":canvasKey="canvasKey":myDrawList="myDrawList":myRoiType="myRoiType"/><el-select v-model="canvasKey" style="width: 100px" size="mini"><el-option value="first" label="数据1"></el-option><el-option value="second" label="数据2"></el-option><el-option value="third" label="数据3"></el-option></el-select><el-selectv-model="myRoiType"style="width: 100px; margin: 10px"size="mini"><el-option value="1" label="区域"></el-option><el-option value="2" label="线条"></el-option><el-option value="3" label="区域加线条"></el-option></el-select><el-button type="primary" @click="saveFunc" size="mini">保存</el-button></div>
</template><script>
import Cookies from "js-cookie";
import Canvas from "./canvas.vue";
export default {data() {return {canvasKey: "first",myDrawList: [],myRoiType: "1",};},components: { Canvas },created() {this.myDrawList = JSON.parse(Cookies.get("myDrawList") || "[]");console.log("取值", this.myDrawList);},methods: {saveFunc() {var arr = this.$refs.drawArea.getData();Cookies.set("myDrawList", JSON.stringify(arr));console.log("保存", arr);},},
};
</script>
<style scoped></style>

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

相关文章:

Vue canvas画图画线例子,数据回显与隔离,点拖拽修改

组件 <template><divstyle"display: flex; height: 342px; width: 760px; border: 1px solid #000"><divstyle"position: relative; height: 100%; width: 608px; min-width: 608px"><canvasid"mycanvas"ref"mycanva…...

Python实现CAN FD 通信(基于PCAN开发CAN FD测试工具)

目录 一.背景 二. 硬件环境 1.CAN通信设备之PCAN 2.物理架构图 三. 资料分析 四. 二次开发 五. 应用 六. 总结 一.背景 在汽车电子领域中CAN是一种被广泛应用的通信协议,CAN 是controller area network 的缩写(以下称为can),是iso国际标准化的串行通信协议。 关于…...

LeetCode--347. 前 K 个高频元素/Golang中的堆(container/heap)

例题链接-前k个高频元素 前言 以前都是用的C写算法题&#xff0c;最近也想熟悉一下golang的数据结构&#xff0c;故来一篇题解堆分析。 正文 这里重点不在分析题目&#xff0c;在于golang中的 container/heap 对于内部实现逻辑有兴趣的可以去看看源码。 这里先给出题解的代…...

关于大数据

在大数据背景下存在的问题&#xff1a; 非结构化、半结构化数据&#xff1a;NoSQL数据库只负责存储&#xff1b;程序处理时涉及到数据移动&#xff0c;速度慢 是否存在一套整体解决方案&#xff1f; 可以存储并处理海量结构化、半结构化、非结构化数据 处理海量数据的速…...

9-收纳的知识

[ComponentOf(typeof(xxx))]组件描述&#xff0c;表示是哪个实体的组件 [EntitySystemOf(typeof(xxx))] 系统描述 [Event(SceneType.Demo)] 定义事件&#xff0c;在指定场景的指定事件发生后触发 [ChildOf(typeof(ComputersComponent))] 标明是谁的子实体 [ResponseType(na…...

堆的实现——堆的应用(堆排序)

文章目录 1.堆的实现2.堆的应用--堆排序 大家在学堆的时候&#xff0c;需要有二叉树的基础知识&#xff0c;大家可以看我的二叉树文章&#xff1a;二叉树 1.堆的实现 如果有⼀个关键码的集合 K {k0 , k1 , k2 , …&#xff0c;kn−1 } &#xff0c;把它的所有元素按完全⼆叉树…...

机器学习6-全连接神经网络2

机器学习6-全连接神经网络2-梯度算法改进 梯度下降算法存在的问题动量法与自适应梯度动量法一、动量法的核心思想二、动量法的数学表示三、动量法的作用四、动量法的应用五、示例 自适应梯度与RMSProp 权值初始化随机权值初始化Xavier初始化HE初始化(MSRA) ![在这里插入图片描述…...

基于 SpringBoot 的电影购票系统

基于SpringBoot的电影购票系统是一个集成了现代化Web开发技术的在线电影票务平台。以下是对该系统的详细介绍&#xff1a; 一、系统背景与意义 随着电影行业的快速发展和观众对观影体验的不断追求&#xff0c;电影票务管理面临着越来越多的挑战。传统的票务管理方式存在效率低…...

C++SLT(三)——list

目录 一、list的介绍二、list的使用list的定义方式 三、list的插入和删除push_back和pop_backpush_front和pop_frontinserterase 四、list的迭代器使用五、list的元素获取六、list的大小控制七、list的操作函数sort和reversemergeremoveremove_ifuniqueassignswap 一、list的介…...

C++ Primer 算术运算符

欢迎阅读我的 【CPrimer】专栏 专栏简介&#xff1a;本专栏主要面向C初学者&#xff0c;解释C的一些基本概念和基础语言特性&#xff0c;涉及C标准库的用法&#xff0c;面向对象特性&#xff0c;泛型特性高级用法。通过使用标准库中定义的抽象设施&#xff0c;使你更加适应高级…...

数据结构-堆和PriorityQueue

1.堆&#xff08;Heap&#xff09; 1.1堆的概念 堆是一种非常重要的数据结构&#xff0c;通常被实现为一种特殊的完全二叉树 如果有一个关键码的集合K{k0,k1,k2,...,kn-1}&#xff0c;把它所有的元素按照完全二叉树的顺序存储在一个一维数组中&#xff0c;如果满足ki<k2i…...

【玩转 Postman 接口测试与开发2_017】第13章:在 Postman 中实现契约测试(Contract Testing)与 API 接口验证(下)

《API Testing and Development with Postman》最新第二版封面 文章目录 第十三章 契约测试与 API 接口验证8 导入官方契约测试集合9 契约测试集合的详细配置9.1 env-apiKey 的创建与设置9.2 env-workspaceId 的设置9.3 Mock 服务器及 env-server 的配置9.4 API 测试实例的配置…...

R语言 | 使用 ComplexHeatmap 绘制热图,分区并给对角线分区加黑边框

目的&#xff1a;画热图&#xff0c;分区&#xff0c;给对角线分区添加黑色边框 建议直接看0和4。 0. 准备数据 # 安装并加载必要的包 #install.packages("ComplexHeatmap") # 如果尚未安装 library(ComplexHeatmap)# 使用 iris 数据集 #data(iris)# 选择数值列&a…...

React图标库: 使用React Icons实现定制化图标效果

React图标库: 使用React Icons实现定制化图标效果 图标库介绍 是一个专门为React应用设计的图标库&#xff0c;它包含了丰富的图标集合&#xff0c;覆盖了常用的图标类型&#xff0c;如FontAwesome、Material Design等。React Icons可以让开发者在React应用中轻松地添加、定制各…...

Python sider-ai-api库 — 访问Claude、llama、ChatGPT、gemini、o1等大模型API

目前国内少有调用ChatGPT、Claude、Gemini等国外大模型API的库。 Python库sider_ai_api 提供了调用这些大模型的一个完整解决方案&#xff0c; 使得开发者能调用 sider.ai 的API&#xff0c;实现大模型的访问。 Sider是谷歌浏览器和Edge的插件&#xff0c;能调用ChatGPT、Clau…...

DeepSeek、哪吒和数据库:厚积薄发的力量

以下有部分来源于AI&#xff0c;毕竟我认为AI还不能替代&#xff0c;他只能是辅助 快速迭代是应用程序不是工程 在这个追求快速迭代、小步快跑的时代&#xff0c;我们似乎总是被 “快” 的节奏裹挟着前进。但当我们静下心来&#xff0c;审视 DeepSeek 的发展、饺子导演创作哪吒…...

DDD - 微服务架构模型_领域驱动设计(DDD)分层架构 vs 整洁架构(洋葱架构) vs 六边形架构(端口-适配器架构)

文章目录 引言1. 概述2. 领域驱动设计&#xff08;DDD&#xff09;分层架构模型2.1 DDD的核心概念2.2 DDD架构分层解析 3. 整洁架构&#xff1a;洋葱架构与依赖倒置3.1 整洁架构的核心思想3.2 整洁架构的层次结构 4. 六边形架构&#xff1a;解耦核心业务与外部系统4.1 六边形架…...

第 1 天:UE5 C++ 开发环境搭建,全流程指南

&#x1f3af; 目标&#xff1a;搭建 Unreal Engine 5&#xff08;UE5&#xff09;C 开发环境&#xff0c;配置 Visual Studio 并成功运行 C 代码&#xff01; 1️⃣ Unreal Engine 5 安装 &#x1f539; 下载与安装 Unreal Engine 5 步骤&#xff1a; 注册并安装 Epic Game…...

【华为OD-E卷 - 109 磁盘容量排序 100分(python、java、c++、js、c)】

【华为OD-E卷 - 磁盘容量排序 100分&#xff08;python、java、c、js、c&#xff09;】 题目 磁盘的容量单位常用的有M&#xff0c;G&#xff0c;T这三个等级&#xff0c; 它们之间的换算关系为1T 1024G&#xff0c;1G 1024M&#xff0c; 现在给定n块磁盘的容量&#xff0c…...

【大数据技术】编写Python代码实现词频统计(python+hadoop+mapreduce+yarn)

编写Python代码实现词频统计(python+hadoop+mapreduce+yarn) 搭建完全分布式高可用大数据集群(VMware+CentOS+FinalShell) 搭建完全分布式高可用大数据集群(Hadoop+MapReduce+Yarn) 本机PyCharm连接CentOS虚拟机 在阅读本文前,请确保已经阅读过以上三篇文章,成功搭建了…...

5-Scene层级关系

Fiber里有个scene是只读属性&#xff0c;能从fiber中获取它属于哪个场景&#xff0c;scene实体中又声明了fiber&#xff0c;fiber与scene是互相引用的关系。 scene层级关系 举例 在unity.core中的EntityHelper中&#xff0c;可以通过entity获取对应的scene root fiber等属性…...

JVM执行流程与架构(对应不同版本JDK)

直接上图&#xff08;对应JDK8以及以后的HotSpot&#xff09; 这里主要区分说明一下 方法区于 字符串常量池 的位置更迭&#xff1a; 方法区 JDK7 以及之前的版本将方法区存放在堆区域中的 永久代空间&#xff0c;堆的大小由虚拟机参数来控制。 JDK8 以及之后的版本将方法…...

本地部署 DeepSeek-R1:简单易上手,AI 随时可用!

&#x1f3af; 先看看本地部署的运行效果 为了测试本地部署的 DeepSeek-R1 是否真的够强&#xff0c;我们随便问了一道经典的“鸡兔同笼”问题&#xff0c;考察它的推理能力。 &#x1f4cc; 问题示例&#xff1a; 笼子里有鸡和兔&#xff0c;总共有 35 只头&#xff0c;94 只…...

请求响应(接上篇)

请求 日期参数 需要在前面加上一个注解DateTimeFormat来接收传入的参数的值 Json参数 JSON参数&#xff1a;JSON数据键名与形参对象属性名相同&#xff0c;定义POJO类型形参即可接收参数&#xff0c;需要使用 RequestBody 标识 通过RequestBody将JSON格式的数据封装到实体类…...

数组排序算法

数组排序算法 用C语言实现的数组排序算法。 排序算法平均时间复杂度最坏时间复杂度最好时间复杂度空间复杂度是否稳定适用场景QuickO(n log n)O(n)O(n log n)O(log n)不稳定大规模数据&#xff0c;通用排序BubbleO(n)O(n)O(n)O(1)稳定小规模数据&#xff0c;教学用途InsertO(n)…...

防火墙的安全策略

1.VLAN 2属于办公区;VLAN 3属于生产区&#xff0c;创建时间段 [FW]ip address-set BG type object [FW-object-address-set-BG]address 192.168.1.0 mask 25 [FW]ip address-set SC type object [FW-object-address-set-SC]address 192.168.1.129 mask 25 [FW]ip address-se…...

2025Java面试题超详细整理《微服务篇》

什么是微服务架构&#xff1f; 微服务框架是将某个应用程序开发划分为许多独立小型服务&#xff0c;实现敏捷开发和部署&#xff0c;这些服务一般围绕业务规则进行构建&#xff0c;可以用不同的语言开发&#xff0c;使用不同的数据存储&#xff0c;最终使得每个服务运行在自己…...

中位数定理:小试牛刀> _ <2025牛客寒假1

给定数轴上的n个点&#xff0c;找出一个到它们的距离之和尽量小的点&#xff08;即使我们可以选择不是这些点里的点&#xff0c;我们还是选择中位数的那个点最优&#xff09; 结论:这些点的中位数就是目标点。可以自己枚举推导&#xff08;很好想&#xff09; (对于 点的数量为…...

(2025,LLM,下一 token 预测,扩散微调,L2D,推理增强,可扩展计算)从大语言模型到扩散微调

Large Language Models to Diffusion Finetuning 目录 1. 概述 2. 研究背景 3. 方法 3.1 用于 LM 微调的高斯扩散 3.2 架构 4. 主要实验结果 5. 结论 1. 概述 本文提出了一种新的微调方法——LM to Diffusion (L2D)&#xff0c;旨在赋予预训练的大语言模型&#xff08;…...

如何开发一个大语言模型,开发流程及需要的专业知识

开发大型语言模型&#xff08;LLM&#xff09;是一个复杂且资源密集的过程&#xff0c;涉及多个阶段和跨学科知识。以下是详细的开发流程和所需专业知识指南&#xff1a; 一、开发流程 1. 需求分析与规划 目标定义&#xff1a;明确模型用途&#xff08;如对话、翻译、代码生成…...