用 three.js 绘制三维带箭头线 (线内箭头)
在LineMaterial.js基础上修改的ArrowLineMaterial.js代码:


- /**
- * @author WestLangley / http://github.com/WestLangley
- *
- * parameters = {
- * color: <hex>,
- * linewidth: <float>,
- * dashed: <boolean>,
- * dashScale: <float>,
- * dashSize: <float>,
- * gapSize: <float>,
- * resolution: <Vector2>, // to be set by renderer
- * }
- */
- import {
- ShaderLib,
- ShaderMaterial,
- UniformsLib,
- UniformsUtils,
- Vector2
- } from "../build/three.module.js";
- UniformsLib.line = {
- linewidth: { value: 1 },
- resolution: { value: new Vector2(1, 1) },
- dashScale: { value: 1 },
- dashSize: { value: 1 },
- gapSize: { value: 1 } // todo FIX - maybe change to totalSize
- };
- ShaderLib['line'] = {
- uniforms: UniformsUtils.merge([
- UniformsLib.common,
- UniformsLib.fog,
- UniformsLib.line
- ]),
- vertexShader:
- `
- #include <common>
- #include <color_pars_vertex>
- #include <fog_pars_vertex>
- #include <logdepthbuf_pars_vertex>
- #include <clipping_planes_pars_vertex>
- uniform float linewidth;
- uniform vec2 resolution;
- attribute vec3 instanceStart;
- attribute vec3 instanceEnd;
- attribute vec3 instanceColorStart;
- attribute vec3 instanceColorEnd;
- varying vec2 vUv;
- varying float lineLength;
- #ifdef USE_DASH
- uniform float dashScale;
- attribute float instanceDistanceStart;
- attribute float instanceDistanceEnd;
- varying float vLineDistance;
- #endif
- void trimSegment( const in vec4 start, inout vec4 end ) {
- // trim end segment so it terminates between the camera plane and the near plane
- // conservative estimate of the near plane
- float a = projectionMatrix[ 2 ][ 2 ]; // 3nd entry in 3th column
- float b = projectionMatrix[ 3 ][ 2 ]; // 3nd entry in 4th column
- float nearEstimate = - 0.5 * b / a;
- float alpha = ( nearEstimate - start.z ) / ( end.z - start.z );
- end.xyz = mix( start.xyz, end.xyz, alpha );
- }
- void main() {
- #ifdef USE_COLOR
- vColor.xyz = ( position.y < 0.5 ) ? instanceColorStart : instanceColorEnd;
- #endif
- #ifdef USE_DASH
- vLineDistance = ( position.y < 0.5 ) ? dashScale * instanceDistanceStart : dashScale * instanceDistanceEnd;
- #endif
- float aspect = resolution.x / resolution.y;
- vUv = uv;
- // camera space
- vec4 start = modelViewMatrix * vec4( instanceStart, 1.0 );
- vec4 end = modelViewMatrix * vec4( instanceEnd, 1.0 );
- // special case for perspective projection, and segments that terminate either in, or behind, the camera plane
- // clearly the gpu firmware has a way of addressing this issue when projecting into ndc space
- // but we need to perform ndc-space calculations in the shader, so we must address this issue directly
- // perhaps there is a more elegant solution -- WestLangley
- bool perspective = ( projectionMatrix[ 2 ][ 3 ] == - 1.0 ); // 4th entry in the 3rd column
- if ( perspective ) {
- if ( start.z < 0.0 && end.z >= 0.0 ) {
- trimSegment( start, end );
- } else if ( end.z < 0.0 && start.z >= 0.0 ) {
- trimSegment( end, start );
- }
- }
- // clip space
- vec4 clipStart = projectionMatrix * start;
- vec4 clipEnd = projectionMatrix * end;
- // ndc space
- vec2 ndcStart = clipStart.xy / clipStart.w;
- vec2 ndcEnd = clipEnd.xy / clipEnd.w;
- // direction
- vec2 dir = ndcEnd - ndcStart;
- // account for clip-space aspect ratio
- dir.x *= aspect;
- dir = normalize( dir );
- // perpendicular to dir
- vec2 offset = vec2( dir.y, - dir.x );
- // undo aspect ratio adjustment
- dir.x /= aspect;
- offset.x /= aspect;
- // sign flip
- if ( position.x < 0.0 ) offset *= - 1.0;
- // endcaps
- if ( position.y < 0.0 ) {
- offset += - dir;
- } else if ( position.y > 1.0 ) {
- offset += dir;
- }
- // adjust for linewidth
- offset *= linewidth;
- // adjust for clip-space to screen-space conversion // maybe resolution should be based on viewport ...
- offset /= resolution.y;
- // select end
- vec4 clip = ( position.y < 0.5 ) ? clipStart : clipEnd;
- // back to clip space
- offset *= clip.w;
- clip.xy += offset;
- gl_Position = clip;
- vec4 mvPosition = ( position.y < 0.5 ) ? start : end; // this is an approximation
- //lineLength = distance(ndcStart, ndcEnd);
- lineLength = distance(ndcStart, ndcEnd) * (1.57 + abs(atan(dir.x / dir.y))) / 2.0;
- //lineLength = distance(clipStart.xyz, clipEnd.xyz);
- //lineLength = distance(start.xyz, end.xyz);
- #include <logdepthbuf_vertex>
- #include <clipping_planes_vertex>
- #include <fog_vertex>
- }
- `,
- fragmentShader:
- `
- uniform vec3 diffuse;
- uniform float opacity;
- uniform sampler2D map;
- varying float lineLength;
- #ifdef USE_DASH
- uniform float dashSize;
- uniform float gapSize;
- #endif
- varying float vLineDistance;
- #include <common>
- #include <color_pars_fragment>
- #include <fog_pars_fragment>
- #include <logdepthbuf_pars_fragment>
- #include <clipping_planes_pars_fragment>
- varying vec2 vUv;
- void main() {
- #include <clipping_planes_fragment>
- #ifdef USE_DASH
- if ( vUv.y < - 1.0 || vUv.y > 1.0 ) discard; // discard endcaps
- if ( mod( vLineDistance, dashSize + gapSize ) > dashSize ) discard; // todo - FIX
- #endif
- if ( abs( vUv.y ) > 1.0 ) {
- float a = vUv.x;
- float b = ( vUv.y > 0.0 ) ? vUv.y - 1.0 : vUv.y + 1.0;
- float len2 = a * a + b * b;
- if ( len2 > 1.0 ) discard;
- }
- vec4 diffuseColor = vec4( diffuse, opacity );
- #include <logdepthbuf_fragment>
- #include <color_fragment>
- vec4 c;
- if ( abs( vUv.y ) > 1.0 ) {
- c = vec4(diffuseColor.rgb, diffuseColor.a);
- } else {
- vec2 rpt = vec2(0.5, 1.0);
- rpt.y *= lineLength * 5.0;
- //rpt.y *= lineLength / 500.0;
- rpt.y = floor(rpt.y + 0.5);
- if(rpt.y < 1.0) { rpt.y = 1.0; }
- if(rpt.y > 5.0) { rpt.y = 5.0; }
- c = vec4(1.0, 1.0, 1.0, 1.0);
- c *= texture2D( map, vUv * rpt );
- }
- gl_FragColor = c;
- //#include <premultiplied_alpha_fragment>
- //#include <tonemapping_fragment>
- //#include <encodings_fragment>
- //#include <fog_fragment>
- }
- `
- };
- var ArrowLineMaterial = function (parameters) {
- ShaderMaterial.call(this, {
- type: 'ArrowLineMaterial',
- uniforms: Object.assign({}, UniformsUtils.clone(ShaderLib['line'].uniforms), {
- map: { value: null },
- }),
- vertexShader: ShaderLib['line'].vertexShader,
- fragmentShader: ShaderLib['line'].fragmentShader,
- clipping: true // required for clipping support
- });
- this.dashed = false;
- Object.defineProperties(this, {
- map: {
- enumerable: true,
- get: function () {
- return this.uniforms.map.value;
- },
- set: function (value) {
- this.uniforms.map.value = value;
- }
- },
- color: {
- enumerable: true,
- get: function () {
- return this.uniforms.diffuse.value;
- },
- set: function (value) {
- this.uniforms.diffuse.value = value;
- }
- },
- linewidth: {
- enumerable: true,
- get: function () {
- return this.uniforms.linewidth.value;
- },
- set: function (value) {
- this.uniforms.linewidth.value = value;
- }
- },
- dashScale: {
- enumerable: true,
- get: function () {
- return this.uniforms.dashScale.value;
- },
- set: function (value) {
- this.uniforms.dashScale.value = value;
- }
- },
- dashSize: {
- enumerable: true,
- get: function () {
- return this.uniforms.dashSize.value;
- },
- set: function (value) {
- this.uniforms.dashSize.value = value;
- }
- },
- gapSize: {
- enumerable: true,
- get: function () {
- return this.uniforms.gapSize.value;
- },
- set: function (value) {
- this.uniforms.gapSize.value = value;
- }
- },
- resolution: {
- enumerable: true,
- get: function () {
- return this.uniforms.resolution.value;
- },
- set: function (value) {
- this.uniforms.resolution.value.copy(value);
- }
- }
- });
- this.setValues(parameters);
- };
- ArrowLineMaterial.prototype = Object.create(ShaderMaterial.prototype);
- ArrowLineMaterial.prototype.constructor = ArrowLineMaterial;
- ArrowLineMaterial.prototype.isLineMaterial = true;
- export { ArrowLineMaterial };
ArrowLineMaterial.js中主要修改部分:
在顶点着色器中定义变量:


- varying float lineLength;
在顶点着色器中计算一下线的长度:


- lineLength = distance(ndcStart, ndcEnd) * (1.57 + abs(atan(dir.x / dir.y))) / 2.0;
在片元着色器中定义变量:


- uniform sampler2D map;
- varying float lineLength;
在片元着色器中贴图:


- vec4 c;
- if ( abs( vUv.y ) > 1.0 ) {
- c = vec4(diffuseColor.rgb, diffuseColor.a);
- } else {
- vec2 rpt = vec2(0.5, 1.0);
- rpt.y *= lineLength * 5.0;
- //rpt.y *= lineLength / 500.0;
- rpt.y = floor(rpt.y + 0.5);
- if(rpt.y < 1.0) { rpt.y = 1.0; }
- if(rpt.y > 5.0) { rpt.y = 5.0; }
- c = vec4(1.0, 1.0, 1.0, 1.0);
- c *= texture2D( map, vUv * rpt );
- }
- gl_FragColor = c;
在片元着色器中注释掉下面几行,使线的颜色和canvas中设置的颜色一致:


- //#include <premultiplied_alpha_fragment>
- //#include <tonemapping_fragment>
- //#include <encodings_fragment>
- //#include <fog_fragment>
CanvasDraw.js代码:


- /**
- * canvas绘图
- */
- let CanvasDraw = function () {
- /**
- * 画文本和气泡
- */
- this.drawText = function (THREE, renderer, text, width) {
- let canvas = document.createElement("canvas");
- let ctx = canvas.getContext('2d');
- canvas.width = width * 2;
- canvas.height = width * 2;
- this.drawBubble(ctx, width - 10, width - 65, width, 45, 6, "#00c864");
- //设置文字
- ctx.fillStyle = "#ffffff";
- ctx.font = '32px 宋体';
- ctx.fillText(text, width - 10 + 12, width - 65 + 34);
- let canvasTexture = new THREE.CanvasTexture(canvas);
- canvasTexture.magFilter = THREE.NearestFilter;
- canvasTexture.minFilter = THREE.NearestFilter;
- let maxAnisotropy = renderer.capabilities.getMaxAnisotropy();
- canvasTexture.anisotropy = maxAnisotropy;
- return canvasTexture;
- }
- /**
- * 画箭头
- */
- this.drawArrow = function (THREE, renderer, width, height) {
- let canvas = document.createElement("canvas");
- let ctx = canvas.getContext('2d');
- canvas.width = width;
- canvas.height = height;
- ctx.save();
- ctx.translate(0, 0);
- //this.drawRoundRectPath(ctx, width, height, 0);
- //ctx.fillStyle = "#ffff00";
- //ctx.fill();
- this.drawArrowBorder(ctx, 2, 0, 0, 4, 100, 50, 0, 96, 2, 100, 300, 50);
- ctx.fillStyle = "#ffffff";
- ctx.fill();
- ctx.restore();
- let canvasTexture = new THREE.CanvasTexture(canvas);
- canvasTexture.magFilter = THREE.NearestFilter;
- canvasTexture.minFilter = THREE.NearestFilter;
- let maxAnisotropy = renderer.capabilities.getMaxAnisotropy();
- canvasTexture.anisotropy = maxAnisotropy;
- return canvasTexture;
- }
- /**
- * 画线内箭头
- */
- this.drawArrow3 = function (THREE, renderer, width, height, color) {
- let canvas = document.createElement("canvas");
- let ctx = canvas.getContext('2d');
- canvas.width = width;
- canvas.height = height;
- ctx.save();
- ctx.translate(0, 0);
- this.drawRoundRectPath(ctx, width, height, 0);
- ctx.fillStyle = color;
- ctx.fill();
- this.drawArrowBorder(ctx, 0, 350, 0, 400, 50, 450, 100, 400, 100, 350, 50, 400);
- ctx.fillStyle = "#ffffff";
- ctx.fill();
- ctx.restore();
- let canvasTexture = new THREE.CanvasTexture(canvas);
- canvasTexture.magFilter = THREE.NearestFilter;
- canvasTexture.minFilter = THREE.NearestFilter;
- canvasTexture.wrapS = THREE.RepeatWrapping;
- canvasTexture.wrapT = THREE.RepeatWrapping;
- let maxAnisotropy = renderer.capabilities.getMaxAnisotropy();
- canvasTexture.anisotropy = maxAnisotropy;
- return canvasTexture;
- }
- /**
- * 画气泡
- */
- this.drawBubble = function (ctx, x, y, width, height, radius, fillColor) {
- ctx.save();
- ctx.translate(x, y);
- this.drawRoundRectPath(ctx, width, height, radius);
- ctx.fillStyle = fillColor || "#000";
- ctx.fill();
- this.drawTriangle(ctx, 20, height, 40, height, 10, 65);
- ctx.fillStyle = fillColor || "#000";
- ctx.fill();
- ctx.restore();
- }
- /**
- * 画三角形
- */
- this.drawTriangle = function (ctx, x1, y1, x2, y2, x3, y3) {
- ctx.beginPath();
- ctx.moveTo(x1, y1);
- ctx.lineTo(x2, y2);
- ctx.lineTo(x3, y3);
- ctx.closePath();
- }
- /**
- * 画箭头边框
- */
- this.drawArrowBorder = function (ctx, x1, y1, x2, y2, x3, y3, x4, y4, x5, y5, x6, y6) {
- ctx.beginPath();
- ctx.moveTo(x1, y1);
- ctx.lineTo(x2, y2);
- ctx.lineTo(x3, y3);
- ctx.lineTo(x4, y4);
- ctx.lineTo(x5, y5);
- ctx.lineTo(x6, y6);
- ctx.closePath();
- }
- /**
- * 画圆角矩形
- */
- this.drawRoundRectPath = function (ctx, width, height, radius) {
- ctx.beginPath(0);
- //从右下角顺时针绘制,弧度从0到1/2PI
- ctx.arc(width - radius, height - radius, radius, 0, Math.PI / 2);
- //矩形下边线
- ctx.lineTo(radius, height);
- //左下角圆弧,弧度从1/2PI到PI
- ctx.arc(radius, height - radius, radius, Math.PI / 2, Math.PI);
- //矩形左边线
- ctx.lineTo(0, radius);
- //左上角圆弧,弧度从PI到3/2PI
- ctx.arc(radius, radius, radius, Math.PI, Math.PI * 3 / 2);
- //上边线
- ctx.lineTo(width - radius, 0);
- //右上角圆弧
- ctx.arc(width - radius, radius, radius, Math.PI * 3 / 2, Math.PI * 2);
- //右边线
- ctx.lineTo(width, height - radius);
- ctx.closePath();
- }
- /**
- * 画圆
- */
- this.drawCircle = function (THREE, renderer, width, height, radius, fillColor) {
- let canvas = document.createElement("canvas");
- let ctx = canvas.getContext('2d');
- canvas.width = width;
- canvas.height = height;
- ctx.save();
- ctx.beginPath(0);
- ctx.arc(width / 2, height / 2, radius, 0, 2 * Math.PI);
- ctx.closePath();
- ctx.fillStyle = fillColor || "#000";
- ctx.fill();
- ctx.restore();
- let texture = new THREE.CanvasTexture(canvas);
- texture.needsUpdate = true;
- texture.magFilter = THREE.NearestFilter;
- texture.minFilter = THREE.NearestFilter;
- let maxAnisotropy = renderer.capabilities.getMaxAnisotropy();
- texture.anisotropy = maxAnisotropy;
- return texture;
- }
- }
- CanvasDraw.prototype.constructor = CanvasDraw;
- export { CanvasDraw }
DrawPath2.js代码:


- /**
- * 绘制路线
- */
- import * as THREE from '../build/three.module.js';
- import { Line2 } from '../js/lines/Line2.js';
- import { LineGeometry } from '../js/lines/LineGeometry.js';
- import { CanvasDraw } from '../js.my/CanvasDraw.js';
- import { ArrowLineMaterial } from '../js.my/ArrowLineMaterial.js';
- import { Utils } from '../js.my/Utils.js';
- import { Msg } from '../js.my/Msg.js';
- let DrawPath2 = function () {
- let _self = this;
- let _canvasDraw = new CanvasDraw();
- let utils = new Utils();
- let msg = new Msg();
- this._isDrawing = false;
- this._path = [];
- this._lines = [];
- this.color = '#00F300';
- this._depthTest = true;
- this._hide = false;
- let _side = 0;
- let viewerContainerId = '#threeCanvas';
- let viewerContainer = $(viewerContainerId)[0];
- let objects;
- let camera;
- let turn;
- let scene;
- this.config = function (objects_, camera_, scene_, turn_) {
- objects = objects_;
- camera = camera_;
- turn = turn_;
- scene = scene_;
- this._oldDistance = 1;
- this._oldCameraPos = { x: camera.position.x, y: camera.position.y, z: camera.position.z }
- }
- this.start = function () {
- if (!this._isDrawing) {
- this._isDrawing = true;
- viewerContainer.addEventListener('click', ray);
- viewerContainer.addEventListener('mousedown', mousedown);
- viewerContainer.addEventListener('mouseup', mouseup);
- }
- }
- this.stop = function () {
- if (this._isDrawing) {
- this._isDrawing = false;
- viewerContainer.removeEventListener('click', ray);
- viewerContainer.removeEventListener('mousedown', mousedown);
- viewerContainer.removeEventListener('mouseup', mouseup);
- }
- }
- function mousedown(params) {
- this._mousedownPosition = { x: camera.position.x, y: camera.position.y, z: camera.position.z }
- }
- function mouseup(params) {
- this._mouseupPosition = { x: camera.position.x, y: camera.position.y, z: camera.position.z }
- }
- function ray(e) {
- turn.unFocusButton();
- let raycaster = createRaycaster(e.clientX, e.clientY);
- let objs = [];
- objects.all.map(object => {
- if (object.material.visible) {
- objs.push(object);
- }
- });
- let intersects = raycaster.intersectObjects(objs);
- if (intersects.length > 0) {
- let point = intersects[0].point;
- let distance = utils.distance(this._mousedownPosition.x, this._mousedownPosition.y, this._mousedownPosition.z, this._mouseupPosition.x, this._mouseupPosition.y, this._mouseupPosition.z);
- if (distance < 5) {
- _self._path.push({ x: point.x, y: point.y + 50, z: point.z });
- if (_self._path.length > 1) {
- let point1 = _self._path[_self._path.length - 2];
- let point2 = _self._path[_self._path.length - 1];
- drawLine(point1, point2);
- }
- }
- }
- }
- function createRaycaster(clientX, clientY) {
- let x = (clientX / $(viewerContainerId).width()) * 2 - 1;
- let y = -(clientY / $(viewerContainerId).height()) * 2 + 1;
- let standardVector = new THREE.Vector3(x, y, 0.5);
- let worldVector = standardVector.unproject(camera);
- let ray = worldVector.sub(camera.position).normalize();
- let raycaster = new THREE.Raycaster(camera.position, ray);
- return raycaster;
- }
- this.refresh = function () {
- }
- function drawLine(point1, point2) {
- let n = Math.round(utils.distance(point1.x, point1.y, point1.z, point2.x, point2.y, point2.z) / 500);
- if (n < 1) n = 1;
- for (let i = 0; i < n; i++) {
- let p1 = {};
- p1.x = point1.x + (point2.x - point1.x) / n * i;
- p1.y = point1.y + (point2.y - point1.y) / n * i;
- p1.z = point1.z + (point2.z - point1.z) / n * i;
- let p2 = {};
- p2.x = point1.x + (point2.x - point1.x) / n * (i + 1);
- p2.y = point1.y + (point2.y - point1.y) / n * (i + 1);
- p2.z = point1.z + (point2.z - point1.z) / n * (i + 1);
- drawLine2(p1, p2);
- }
- }
- function drawLine2(point1, point2) {
- const positions = [];
- positions.push(point1.x / 50, point1.y / 50, point1.z / 50);
- positions.push(point2.x / 50, point2.y / 50, point2.z / 50);
- let geometry = new LineGeometry();
- geometry.setPositions(positions);
- geometry.setColors([
- parseInt(_self.color.substr(1, 2), 16) / 256,
- parseInt(_self.color.substr(3, 2), 16) / 256,
- parseInt(_self.color.substr(5, 2), 16) / 256,
- parseInt(_self.color.substr(1, 2), 16) / 256,
- parseInt(_self.color.substr(3, 2), 16) / 256,
- parseInt(_self.color.substr(5, 2), 16) / 256
- ]);
- let canvasTexture = _canvasDraw.drawArrow3(THREE, renderer, 100, 800, _self.color); //箭头
- let matLine = new ArrowLineMaterial({
- map: canvasTexture,
- color: new THREE.Color(0xffffff),
- linewidth: 0.005, // in world units with size attenuation, pixels otherwise
- dashed: false,
- depthTest: _self._depthTest,
- side: _side,
- vertexColors: THREE.VertexColors,
- resolution: new THREE.Vector2(1, $(viewerContainerId).height() / $(viewerContainerId).width())
- });
- let line = new Line2(geometry, matLine);
- line.computeLineDistances();
- line.scale.set(50, 50, 50);
- scene.add(line);
- _self._lines.push(line);
- }
- this.setDepthTest = function (bl) {
- if (bl) {
- _self._depthTest = true;
- this._lines.map(line => {
- line.material.depthTest = true;
- line.material.side = 0;
- });
- } else {
- _self._depthTest = false;
- this._lines.map(line => {
- line.material.depthTest = false;
- line.material.side = THREE.DoubleSide;
- });
- }
- }
- this.getPath = function () {
- return this._path;
- }
- this.hide = function () {
- this._lines.map(line => scene.remove(line));
- this._hide = true;
- }
- this.show = function () {
- this._lines.map(line => scene.add(line));
- this._hide = false;
- }
- this.isShow = function () {
- return !this._hide;
- }
- this.create = function (path, color) {
- _self.color = color;
- _self._path = path;
- if (_self._path.length > 1) {
- for (let i = 0; i < _self._path.length - 1; i++) {
- let point1 = _self._path[i];
- let point2 = _self._path[i + 1];
- drawLine(point1, point2);
- }
- }
- }
- this.getDepthTest = function () {
- return _self._depthTest;
- }
- this.undo = function () {
- scene.remove(this._lines[this._lines.length - 1]);
- _self._path.splice(this._path.length - 1, 1);
- _self._lines.splice(this._lines.length - 1, 1);
- }
- }
- DrawPath2.prototype.constructor = DrawPath2;
- export { DrawPath2 }
效果图:
缺陷:
2.5D视角观察,看着还行,但是把相机拉近观察,箭头就会变形。凑合着用。
箭头贴图变形或者箭头显示不全,原因我猜可能是因为在场景中,线的远离相机的一端,在标准设备坐标系中比较细,线的靠近相机的一端,在标准设备坐标系中比较粗,但为了使线的粗细一样,靠近相机的一端被裁剪了,所以箭头可能会显示不全。
不管是MeshLine还是three.js的Line2,这个带宽度的线,和三维场景中的三维模型是有区别的,无论场景拉近还是拉远,线的宽度不变,而三维模型场景拉远变小,拉近变大。
Drawing arrow lines is hard!
参考文章:
https://www.cnblogs.com/dojo-lzz/p/9219290.html
https://blog.csdn.net/Amesteur/article/details/95964526
用 three.js 绘制三维带箭头线 (线内箭头)的更多相关文章
- OpenLayer——绘制带箭头的线
绘制带箭头的线,计算相对复杂,多少是有点影响性能了.更简单的做法:初始.目标点用不同的点进行强调即可. <!DOCTYPE html> <html lang="en&quo ...
- 如何利用百度地图JSAPI画带箭头的线?
百度地图JSAPI提供两种绘制多折线的方式,一种是已知多折线经纬度坐标串通过AddOverlay接口进行添加:另一种是通过在地图上鼠标单击进行绘制(鼠标绘制工具条库).目前这两种方式只能绘制多折线,并 ...
- AE常用代码(标注要素、AE中画带箭头的线、如何获得投影坐标、参考坐标、投影方式、FeatureCount注意事项)
手上的电脑已经用了将近三年了,想入手一台Surface Pro,所以计划着把电脑上的资料整理下,部分资料打算发到博客上来,资料有同事.也有自己的.也有来自网络的,来源途径太多,也没法详细注明,请见谅! ...
- 使用原生JavaScript的Canvas实现拖拽式图形绘制,支持画笔、线条、箭头、三角形、矩形、平行四边形、梯形以及多边形和圆形,不依赖任何库和插件,有演示demo
前言 需要用到图形绘制,没有找到完整的图形绘制实现,所以自己实现了一个 - - 一.实现的功能 1.基于oop思想构建,支持坐标点.线条(由坐标点组成,包含方向).多边形(由多个坐标点组成).圆形(包 ...
- Matlab绘图基础——绘制三维表面
%绘制三维表面 ------------------------------------- %1.绘制线框图:mesh:每一条曲线称为mesh line %首先利用meshgrid函数产生平面区域内的 ...
- Matlab绘图基础——绘制三维曲线
%% 绘制三维曲线 %plot3函数,其中每一组x,y,z组成一组曲线的坐标参数,选项的定义和plot函数相同. %1.当x,y,z是同维向量时,则x,y,z 对应元素构成一条三维曲线. x0 = 0 ...
- three.js 3d三维网页代码加密的实现方法
http://www.jiamisoft.com/blog/17827-three-js-3dsanweiwangyejiami.html https://www.html5tricks.com/ta ...
- js 绘制数学函数
<!-- <!doctype html> --> <html lang="en"> <head> <meta charset= ...
- 使用Matlab绘制三维图的几种方法
以下六个函数都可以实现绘制三维图像: surf(xx,yy,zz); surfc(xx,yy,zz); mesh(xx,yy,zz); meshc(xx,yy,zz); meshz(xx,yy,zz) ...
- 【转】JS大总结(带实例)
JS大总结(带实例) JavaScript事务查询综合click() 对象.click() 使对象被点击.closed 对象.closed 对象窗口是否已封闭true/falseclearTimeou ...
随机推荐
- 【uniapp】学习笔记day02 | uniapp搭建
起因:需要做一个小程序,家人们谁懂啊,老师我真的不会做,由于懒得看视频学习,于是只能看博客学习了. uniapp 好处: 1.不用关心适配问题 2.可以发布到各大平台的小程序 3.上手容易,使用vue ...
- lua面向对象(类)和lua协同线程与协同函数、Lua文件I/O
-- create a class Animal={name = "no_name" , age=0 } function Animal:bark(voice) print(sel ...
- vertx 的http服务表单提交与mysql验证
1.依赖 <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http:/ ...
- C++学习笔记二:变量与数据类型(整型)
1.int(整型数据): 1.1 进制的表示:十进制,八进制,16进制,二进制 int number1 = 15; // Decimal int number2 = 017; // Octal int ...
- VUE路由基本操作
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...
- CH395实现主动ping对端功能(代码及说明)
目录 1.PING原理 1.1简介 1.2协议 1.3通信流程 2.代码解释 3.工程链接 PING原理 1.简介 PING是基于ICMP(Internet Control Message Proto ...
- .NET周刊【12月第2期 2023-12-13】
国内文章 用最清爽的方式开发dotNet https://www.cnblogs.com/ncellit/p/17881779.html 本文介绍了如何以清爽的方式开发dotNet应用,特别是简单的A ...
- MongoDB副本集的搭建和管理(高可用)
使得mongodb具备自动故障转移.高可用.读写分离. 副本集默认情况下读写都只是通过主库,副节点只是备份数据而已,但是可以设置副节点允许读操作,这样就可以做成读写分离. 使用pymongo的时候也可 ...
- 使用kubeadm在Centos8上部署kubernetes1.18
// 查看系统版本 cat /etc/centos-release CentOS Linux release 8.1.1911 (Core) // 如果系统环境为8.0(云服务器默认最大安装环境为8. ...
- JPA复杂查询时间查询分页排序
JPA复杂查询时间查询分页排序 JPA复杂查询时间查询分页排序,工作上用到,因为项目是jpa,记录.代码囊括了:查询条件+时间范围+分页+排序 其实我也不太想用jpa,但是他也有优点,操作可以兼容多种 ...