vtk.js

vtk.js


实例_尺度标定画布

<h3>构造函数</h3> <pre><code class="language-javascript">constructor(vm) { this.vm = vm; // 绑定页面实例 // 定义class前缀 this.pifix = 'RF-SCALECALIBRATION-'; // 默认绘制的是线段 this.type = 'line'; }</code></pre> <h3>获取基础缩放比例</h3> <pre><code class="language-javascript">/** * 获取基础缩放比例 * @param {*} svg */ getScale(svg) { let { width, height } = this.vm.$refs.canvasWrap.getBoundingClientRect(); // 如果初始化的时候 拿不到宽高 if (width === 0 || height === 0) { width = this.vm.canvasWidth - 2; height = this.vm.canvasHeight - 76 - 52 - 2; } const minW = Math.min(width, height); // const svgWidth = svg.attr('wrapWidth'); return this.vm.imageWidth / minW; }</code></pre> <h3>创建箭头marker</h3> <pre><code class="language-javascript">/** * 创建箭头marker * @param {*} svg */ createMarker(svg) { svg.append('defs') .html(` &amp;lt;marker id=&amp;quot;SCALECALIBRATIO-marker-end&amp;quot; viewBox=&amp;quot;0 0 10 10&amp;quot; refX=&amp;quot;10&amp;quot; refY=&amp;quot;5&amp;quot; markerWidth=&amp;quot;${this.getScale(svg) * 1.5}&amp;quot; markerHeight=&amp;quot;${this.getScale(svg) * 1.5}&amp;quot; orient=&amp;quot;auto&amp;quot;&amp;gt; &amp;lt;path d=&amp;quot;M 0 0 L 10 5 L 0 10&amp;quot; stroke-width=&amp;quot;1&amp;quot; stroke=&amp;quot;#FF9D28&amp;quot; fill=&amp;quot;none&amp;quot; /&amp;gt; &amp;lt;/marker&amp;gt; &amp;lt;marker id=&amp;quot;SCALECALIBRATIO-marker-start&amp;quot; viewBox=&amp;quot;0 0 10 10&amp;quot; refX=&amp;quot;0&amp;quot; refY=&amp;quot;5&amp;quot; markerWidth=&amp;quot;${this.getScale(svg) * 1.5}&amp;quot; markerHeight=&amp;quot;${this.getScale(svg) * 1.5}&amp;quot; orient=&amp;quot;auto&amp;quot;&amp;gt; &amp;lt;path d=&amp;quot;M 10 0 L 0 5 L 10 10&amp;quot; stroke-width=&amp;quot;1&amp;quot; stroke=&amp;quot;#FF9D28&amp;quot; fill=&amp;quot;none&amp;quot; /&amp;gt; &amp;lt;/marker&amp;gt; `); }</code></pre> <p>指定箭头marker的起始和结尾</p> <h3>绘制线段</h3> <pre><code class="language-javascript">/** * 绘制线 * @param {*} g * @param {*} x1 * @param {*} y1 * @param {*} x2 * @param {*} y2 * @param {*} cls * @param {*} width * @param {*} marker */ drawLine(g, x1, y1, x2, y2, cls, width, marker, svg) { return g.append('line') .attr('class', cls) .attr('x1', x1) .attr('y1', y1) .attr('x2', x2) .attr('y2', y2) .attr('marker-start', marker ? 'url(#SCALECALIBRATIO-marker-start)' : '') .attr('marker-end', marker ? 'url(#SCALECALIBRATIO-marker-end)' : '') .attr('stroke-width', this.getScale(svg) * width) .style('fill', 'none') .style('stroke', '#FF9D28') .style('shape-rendering', 'crispEdges'); // 抗锯齿 }</code></pre> <h3>绘制圆圈</h3> <pre><code class="language-javascript"> /** * 绘制圆圈 * @param {*} g * @param {*} x * @param {*} y * @param {*} r * @param {*} cls * @param {*} svg */ drawCircle(g, x, y, r, cls, svg) { return g.append('circle') .attr('class', cls) .attr('cx', x) .attr('cy', y) .attr('r', this.getScale(svg) * r) .attr('fill', '#FF9D28') .style('cursor', 'pointer'); }</code></pre> <h3>绘制路径</h3> <pre><code class="language-javascript"> /** * 绘制路径 * @param {*} g * @param {*} cls * @param {*} width */ drawPath(g, cls, width, svg) { return g.append('path') .attr('class', cls) .style('stroke-width', this.getScale(svg) * width) .style('stroke', '#FF9D28') .style('stroke-linejoin', 'round') .style('fill', 'none'); }</code></pre> <h3>事件 拖拽Start</h3> <pre><code class="language-javascript">/** * 拖拽开始 * @param {*} e * @param {*} g */ dragStart(e, g, svg) { const { x, y } = e; if (!svg.select('#SCALECALIBRATIO-marker').size()) { this.createMarker(svg); } this.start = { x: x, y: y, g: null }; // 每次重新绘制前移除之前的线 g.selectAll('.RF-canvas-g').remove(); const curg = g.append('g') .attr('class', 'RF-canvas-g'); if (this.type === 'line') { // 线段绘制 this.drawCircle(curg, x, y, 5, `${this.pifix}start`, svg); // 添加path const path = this.drawPath(curg, `${this.pifix}line`, 2, svg); this.start.g = curg; this.start.path = path; } else if (this.type === 'verticalRuler') { // 垂直尺 // &amp;lt;line x1=&amp;quot;0&amp;quot; y1=&amp;quot;0&amp;quot; x2=&amp;quot;200&amp;quot; y2=&amp;quot;200&amp;quot; style=&amp;quot;stroke:rgb(255,0,0);stroke-width:2&amp;quot;/&amp;gt; const x1 = x - this.getScale(svg) * 40; const x2 = x + this.getScale(svg) * 40; // 绘制开始线 this.drawLine(curg, x1, y, x2, y, `${this.pifix}line-start`, 1, false, svg); // 绘制中间线 this.drawLine(curg, x, y, x, y, `${this.pifix}line-middle`, 1, true, svg); this.start.g = curg; } else if (this.type === 'horizontalRuler') { // 水平尺 const y1 = y - this.getScale(svg) * 40; const y2 = y + this.getScale(svg) * 40; // 绘制开始线 this.drawLine(curg, x, y1, x, y2, `${this.pifix}line-start`, 1, false, svg); // 绘制中间线 this.drawLine(curg, x, y, x, y, `${this.pifix}line-middle`, 1, true, svg); this.start.g = curg; } }</code></pre> <h3>事件拖拽move</h3> <pre><code class="language-javascript"> /** * 拖拽move * @param {*} e * @param {*} g */ drag(e, g, svg) { const { x, y } = e; if (this.start) { // 线段绘制 if (this.type === 'line') { this.start.path.attr('d', `M${this.start.x},${this.start.y}L${x},${y}`); } else if (this.type === 'verticalRuler') { // 垂直尺 this.start.g.select(`.${this.pifix}line-middle`) .attr('x2', this.start.x) .attr('y2', y); } else if (this.type === 'horizontalRuler') { // 水平尺 this.start.g.select(`.${this.pifix}line-middle`) .attr('x2', x) .attr('y2', this.start.y); } } }</code></pre> <h3>事件拖拽end</h3> <pre><code class="language-javascript">/** * 拖拽结束 * @param {*} e * @param {*} g */ dragEnd(e, g, svg) { const { x, y } = e; if (this.start) { // 线段绘制 if (this.type === 'line') { this.start.path.attr('d', `M${this.start.x},${this.start.y}L${x},${y}Z`); this.drawCircle(this.start.g, x, y, 5, `${this.pifix}end`, svg); // 触发回调函数 返回坐标 this.vm.operatorCb &amp;amp;&amp;amp; this.vm.operatorCb([ [this.start.x, this.vm.imageHeight - this.start.y], [x, this.vm.imageHeight - y] ], this.vm.getCameraInfo(svg)); // 小圆点可以手动调整位置 this.dragCicle(this.start.g, this.start.path, svg); } else if (this.type === 'verticalRuler') { // 垂直尺 this.start.g.select(`.${this.pifix}line-middle`) .attr('x2', this.start.x) .attr('y2', y); this.drawLine(this.start.g, this.start.x - this.getScale(svg) * 40, y, this.start.x + this.getScale(svg) * 40, y, `${this.pifix}line-end`, 1, false, svg); // 触发回调函数 返回坐标 this.vm.operatorCb &amp;amp;&amp;amp; this.vm.operatorCb([ [this.start.x, this.vm.imageHeight - this.start.y], [this.start.x, this.vm.imageHeight - y] ], this.vm.getCameraInfo(svg)); } else if (this.type === 'horizontalRuler') { // 水平尺 this.start.g.select(`.${this.pifix}line-middle`) .attr('x2', x) .attr('y2', this.start.y); this.drawLine(this.start.g, x, this.start.y - this.getScale(svg) * 40, x, this.start.y + this.getScale(svg) * 40, `${this.pifix}line-end`, 1, false, svg); // 触发回调函数 返回坐标 this.vm.operatorCb &amp;amp;&amp;amp; this.vm.operatorCb([ [this.start.x, this.vm.imageHeight - this.start.y], [x, this.vm.imageHeight - this.start.y] ], this.vm.getCameraInfo(svg)); } } }</code></pre> <h3>原点拖动</h3> <pre><code class="language-javascript">/** * 原点拖动功能 * @param {*} g */ dragCicle(g, path, svg) { const _ = this; g.selectAll('circle') .call(d3.drag() .on('start', () =&amp;gt; { this.startCircleMoveing = true; }) .on('end', function (e) { _.moveCircle(d3.select(this), d3.event, path, true, svg); this.startCircleMoveing = false; }) .on('drag', function (e) { _.moveCircle(d3.select(this), d3.event, path, svg); })); }</code></pre> <h3>圆点移动</h3> <pre><code class="language-javascript">/** * 圆点移动 * @param {*} circle * @param {*} event */ moveCircle(circle, event, path, isEnd, svg) { if (this.startCircleMoveing) { const { dx, dy } = event; const isStart = circle.attr('class') === `${this.pifix}start`; if (isStart) { const newx = Number(circle.attr('cx')) + dx; const newy = Number(circle.attr('cy')) + dy; circle.attr('cx', newx) .attr('cy', newy); // update path path.attr('d', path.attr('d').replace(/M[\d\.,]+/, `M${newx},${newy}`)); } else { const newx = Number(circle.attr('cx')) + dx; const newy = Number(circle.attr('cy')) + dy; circle.attr('cx', newx) .attr('cy', newy); // update path path.attr('d', path.attr('d').replace(/L[\d\.,]+/, `L${newx},${newy}`)); } // M4348.178649902344,764.1790771484375L932.2987060546875,1681.1940307617188Z const arrs = path.attr('d').match(/[\d\.]+/g); // 触发回调函数 返回坐标 if (arrs &amp;amp;&amp;amp; arrs.length === 4) { isEnd &amp;amp;&amp;amp; this.vm.operatorCb &amp;amp;&amp;amp; this.vm.operatorCb([ [arrs[0], this.vm.imageHeight - arrs[1]], [arrs[2], this.vm.imageHeight - arrs[3]] ], this.vm.getCameraInfo(svg)); } } }</code></pre> <h3>清空画布</h3> <pre><code class="language-javascript"> /** * 清空画布 */ clearCanvas(svg) { if (arguments.length) { svg = d3.select(svg); svg.selectAll('.RF-canvas-g').remove(); this.svg = svg; } else { this.svg.selectAll('.RF-canvas-g').remove(); } }</code></pre> <h3>画布回显</h3> <pre><code class="language-javascript">/** * 回显功能 * @param {*} type * @param {*} data * { // 坐标信息 coordinate: [ [1920, 1080], [2920, 3000] ], // 类型 type: 'line' } */ echoCanvas(data, svg) { svg = d3.select(svg); if (!svg.select('#SCALECALIBRATIO-marker').size()) { this.createMarker(svg); } const g = svg.select('.handle-g'); // 每次重新绘制前移除之前的线 g.selectAll('.RF-canvas-g').remove(); const curg = g.append('g').attr('class', 'RF-canvas-g'); // 画线 if (data.type === 'line' &amp;amp;&amp;amp; data.coordinate.length === 2) { // eslint-disable-next-line prefer-const let [x1, y1] = data.coordinate[0]; // eslint-disable-next-line prefer-const let [x2, y2] = data.coordinate[1]; y1 = this.vm.imageHeight - y1; y2 = this.vm.imageHeight - y2; this.drawCircle(curg, x1, y1, 5, `${this.pifix}start`, svg); // 添加path const path = this.drawPath(curg, `${this.pifix}line`, 2, svg); path.attr('d', `M${x1},${y1}L${x2},${y2}Z`); this.drawCircle(curg, x2, y2, 5, `${this.pifix}end`, svg); // 小圆点可以手动调整位置 this.dragCicle(curg, path, svg); } // 垂直尺子 if (data.type === 'verticalRuler' &amp;amp;&amp;amp; data.coordinate.length === 2) { // eslint-disable-next-line prefer-const let [x1, y1] = data.coordinate[0]; // eslint-disable-next-line prefer-const let [x2, y2] = data.coordinate[1]; y1 = this.vm.imageHeight - y1; y2 = this.vm.imageHeight - y2; const xl = x1 - this.getScale(svg) * 40; const xr = x1 + this.getScale(svg) * 40; // 绘制开始线 this.drawLine(curg, xl, y1, xr, y1, `${this.pifix}line-start`, 1, false, svg); // 绘制中间线 this.drawLine(curg, x1, y1, x2, y2, `${this.pifix}line-middle`, 1, true, svg); // 绘制结束线 this.drawLine(curg, xl, y2, xr, y2, `${this.pifix}line-end`, 1, false, svg); } // 水平尺子 if (data.type === 'horizontalRuler' &amp;amp;&amp;amp; data.coordinate.length === 2) { // eslint-disable-next-line prefer-const let [x1, y1] = data.coordinate[0]; // eslint-disable-next-line prefer-const let [x2, y2] = data.coordinate[1]; y1 = this.vm.imageHeight - y1; y2 = this.vm.imageHeight - y2; const yt = y1 - this.getScale(svg) * 40; const yb = y1 + this.getScale(svg) * 40; // 绘制开始线 this.drawLine(curg, x1, yt, x1, yb, `${this.pifix}line-start`, 1, false, svg); // 绘制中间线 this.drawLine(curg, x1, y1, x2, y2, `${this.pifix}line-middle`, 1, true, svg); // 绘制结束线 this.drawLine(curg, x2, yt, x2, yb, `${this.pifix}line-end`, 1, false, svg); } }</code></pre>

页面列表

ITEM_HTML