背景

星座礼物配套的玩法活动,根据当前时间开放对应的星座馆,送出相应的星座礼物有概率为当前星座上的星星命名,依据不同的礼物价值命名不同等级的星星,每个星座星星数量固定点完即止。

选型原因

拆解一下需求:
1、共有12个星座,且每个星座的星星要依据星座的对应形状排列。
2、为了提高参与用户数量,每个星座的星星数量较多,一屏展示不下,用户不仅需要查看整个星座的点亮情况,同时也好奇某颗星星的点亮详情,所以会涉及到频繁的缩放(为了用户的参与体验要支持任意倍数平滑的缩放)和滑动

综上我们选用性能优可控性高的canvas来实现上述功能。

基本概念:

在coding之前我们首先需要了解几个基本概念:画布、画布原点、笔触点、视窗

结合上图笑脸所示,
画布:canvas提供的绘制位置,即笑脸所在的白色正方形是一块提前声明好的画布
画布原点:画布左上角的位置即(0,0)点,向➡️为X轴正方向,向⬇️为Y轴正方向
笔触点:画笔绘制的起始位置; ctx.arc(75, 75, 50, 0, Math.PI * 2, true); // 表示把笔触点移动到(75,75)的位置以50为半径画一个0到360度闭合的圆。笔触点相对于画布原点定位的,可以为负值,不在画布上的绘制则不显示。
视窗:物理设备(手机屏幕或电脑屏幕)的左上角

为何要区分画布和视窗这两个概念?
画布的大小等于视窗的大小,但我们所有的操作都在手机屏幕上进行,即我们可以感知到的操作点都是视窗上的坐标点;但笔触所有的坐标点对应的都是画布的原点,所以需要将两者区别对待。

了解完了基本概念下面我将依照:绘制---->拖拽---->缩放---->优化这个顺序描述关键的实现步骤。

绘制

如下图所示,我声明了一张同视窗尺寸一致的画布,将笔触原点移动至画布(300,100),通过drawImage方法将提前加载的图片设定好宽高后绘制出来,值得一提的是通过drawImage方法实现给图片加水印和前端压缩上传图片都是不错的选择!

拖拽:

拖动图片向左移动1像素的过程:

#mermaid-svg-gIZkmNZC4ODV7ThQ .label{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);fill:#333;color:#333}#mermaid-svg-gIZkmNZC4ODV7ThQ .label text{fill:#333}#mermaid-svg-gIZkmNZC4ODV7ThQ .node rect,#mermaid-svg-gIZkmNZC4ODV7ThQ .node circle,#mermaid-svg-gIZkmNZC4ODV7ThQ .node ellipse,#mermaid-svg-gIZkmNZC4ODV7ThQ .node polygon,#mermaid-svg-gIZkmNZC4ODV7ThQ .node path{fill:#ECECFF;stroke:#9370db;stroke-width:1px}#mermaid-svg-gIZkmNZC4ODV7ThQ .node .label{text-align:center;fill:#333}#mermaid-svg-gIZkmNZC4ODV7ThQ .node.clickable{cursor:pointer}#mermaid-svg-gIZkmNZC4ODV7ThQ .arrowheadPath{fill:#333}#mermaid-svg-gIZkmNZC4ODV7ThQ .edgePath .path{stroke:#333;stroke-width:1.5px}#mermaid-svg-gIZkmNZC4ODV7ThQ .flowchart-link{stroke:#333;fill:none}#mermaid-svg-gIZkmNZC4ODV7ThQ .edgeLabel{background-color:#e8e8e8;text-align:center}#mermaid-svg-gIZkmNZC4ODV7ThQ .edgeLabel rect{opacity:0.9}#mermaid-svg-gIZkmNZC4ODV7ThQ .edgeLabel span{color:#333}#mermaid-svg-gIZkmNZC4ODV7ThQ .cluster rect{fill:#ffffde;stroke:#aa3;stroke-width:1px}#mermaid-svg-gIZkmNZC4ODV7ThQ .cluster text{fill:#333}#mermaid-svg-gIZkmNZC4ODV7ThQ div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);font-size:12px;background:#ffffde;border:1px solid #aa3;border-radius:2px;pointer-events:none;z-index:100}#mermaid-svg-gIZkmNZC4ODV7ThQ .actor{stroke:#ccf;fill:#ECECFF}#mermaid-svg-gIZkmNZC4ODV7ThQ text.actor>tspan{fill:#000;stroke:none}#mermaid-svg-gIZkmNZC4ODV7ThQ .actor-line{stroke:grey}#mermaid-svg-gIZkmNZC4ODV7ThQ .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333}#mermaid-svg-gIZkmNZC4ODV7ThQ .messageLine1{stroke-width:1.5;stroke-dasharray:2, 2;stroke:#333}#mermaid-svg-gIZkmNZC4ODV7ThQ #arrowhead path{fill:#333;stroke:#333}#mermaid-svg-gIZkmNZC4ODV7ThQ .sequenceNumber{fill:#fff}#mermaid-svg-gIZkmNZC4ODV7ThQ #sequencenumber{fill:#333}#mermaid-svg-gIZkmNZC4ODV7ThQ #crosshead path{fill:#333;stroke:#333}#mermaid-svg-gIZkmNZC4ODV7ThQ .messageText{fill:#333;stroke:#333}#mermaid-svg-gIZkmNZC4ODV7ThQ .labelBox{stroke:#ccf;fill:#ECECFF}#mermaid-svg-gIZkmNZC4ODV7ThQ .labelText,#mermaid-svg-gIZkmNZC4ODV7ThQ .labelText>tspan{fill:#000;stroke:none}#mermaid-svg-gIZkmNZC4ODV7ThQ .loopText,#mermaid-svg-gIZkmNZC4ODV7ThQ .loopText>tspan{fill:#000;stroke:none}#mermaid-svg-gIZkmNZC4ODV7ThQ .loopLine{stroke-width:2px;stroke-dasharray:2, 2;stroke:#ccf;fill:#ccf}#mermaid-svg-gIZkmNZC4ODV7ThQ .note{stroke:#aa3;fill:#fff5ad}#mermaid-svg-gIZkmNZC4ODV7ThQ .noteText,#mermaid-svg-gIZkmNZC4ODV7ThQ .noteText>tspan{fill:#000;stroke:none}#mermaid-svg-gIZkmNZC4ODV7ThQ .activation0{fill:#f4f4f4;stroke:#666}#mermaid-svg-gIZkmNZC4ODV7ThQ .activation1{fill:#f4f4f4;stroke:#666}#mermaid-svg-gIZkmNZC4ODV7ThQ .activation2{fill:#f4f4f4;stroke:#666}#mermaid-svg-gIZkmNZC4ODV7ThQ .mermaid-main-font{font-family:"trebuchet ms", verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-gIZkmNZC4ODV7ThQ .section{stroke:none;opacity:0.2}#mermaid-svg-gIZkmNZC4ODV7ThQ .section0{fill:rgba(102,102,255,0.49)}#mermaid-svg-gIZkmNZC4ODV7ThQ .section2{fill:#fff400}#mermaid-svg-gIZkmNZC4ODV7ThQ .section1,#mermaid-svg-gIZkmNZC4ODV7ThQ .section3{fill:#fff;opacity:0.2}#mermaid-svg-gIZkmNZC4ODV7ThQ .sectionTitle0{fill:#333}#mermaid-svg-gIZkmNZC4ODV7ThQ .sectionTitle1{fill:#333}#mermaid-svg-gIZkmNZC4ODV7ThQ .sectionTitle2{fill:#333}#mermaid-svg-gIZkmNZC4ODV7ThQ .sectionTitle3{fill:#333}#mermaid-svg-gIZkmNZC4ODV7ThQ .sectionTitle{text-anchor:start;font-size:11px;text-height:14px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-gIZkmNZC4ODV7ThQ .grid .tick{stroke:#d3d3d3;opacity:0.8;shape-rendering:crispEdges}#mermaid-svg-gIZkmNZC4ODV7ThQ .grid .tick text{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-gIZkmNZC4ODV7ThQ .grid path{stroke-width:0}#mermaid-svg-gIZkmNZC4ODV7ThQ .today{fill:none;stroke:red;stroke-width:2px}#mermaid-svg-gIZkmNZC4ODV7ThQ .task{stroke-width:2}#mermaid-svg-gIZkmNZC4ODV7ThQ .taskText{text-anchor:middle;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-gIZkmNZC4ODV7ThQ .taskText:not([font-size]){font-size:11px}#mermaid-svg-gIZkmNZC4ODV7ThQ .taskTextOutsideRight{fill:#000;text-anchor:start;font-size:11px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-gIZkmNZC4ODV7ThQ .taskTextOutsideLeft{fill:#000;text-anchor:end;font-size:11px}#mermaid-svg-gIZkmNZC4ODV7ThQ .task.clickable{cursor:pointer}#mermaid-svg-gIZkmNZC4ODV7ThQ .taskText.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-gIZkmNZC4ODV7ThQ .taskTextOutsideLeft.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-gIZkmNZC4ODV7ThQ .taskTextOutsideRight.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-gIZkmNZC4ODV7ThQ .taskText0,#mermaid-svg-gIZkmNZC4ODV7ThQ .taskText1,#mermaid-svg-gIZkmNZC4ODV7ThQ .taskText2,#mermaid-svg-gIZkmNZC4ODV7ThQ .taskText3{fill:#fff}#mermaid-svg-gIZkmNZC4ODV7ThQ .task0,#mermaid-svg-gIZkmNZC4ODV7ThQ .task1,#mermaid-svg-gIZkmNZC4ODV7ThQ .task2,#mermaid-svg-gIZkmNZC4ODV7ThQ .task3{fill:#8a90dd;stroke:#534fbc}#mermaid-svg-gIZkmNZC4ODV7ThQ .taskTextOutside0,#mermaid-svg-gIZkmNZC4ODV7ThQ .taskTextOutside2{fill:#000}#mermaid-svg-gIZkmNZC4ODV7ThQ .taskTextOutside1,#mermaid-svg-gIZkmNZC4ODV7ThQ .taskTextOutside3{fill:#000}#mermaid-svg-gIZkmNZC4ODV7ThQ .active0,#mermaid-svg-gIZkmNZC4ODV7ThQ .active1,#mermaid-svg-gIZkmNZC4ODV7ThQ .active2,#mermaid-svg-gIZkmNZC4ODV7ThQ .active3{fill:#bfc7ff;stroke:#534fbc}#mermaid-svg-gIZkmNZC4ODV7ThQ .activeText0,#mermaid-svg-gIZkmNZC4ODV7ThQ .activeText1,#mermaid-svg-gIZkmNZC4ODV7ThQ .activeText2,#mermaid-svg-gIZkmNZC4ODV7ThQ .activeText3{fill:#000 !important}#mermaid-svg-gIZkmNZC4ODV7ThQ .done0,#mermaid-svg-gIZkmNZC4ODV7ThQ .done1,#mermaid-svg-gIZkmNZC4ODV7ThQ .done2,#mermaid-svg-gIZkmNZC4ODV7ThQ .done3{stroke:grey;fill:#d3d3d3;stroke-width:2}#mermaid-svg-gIZkmNZC4ODV7ThQ .doneText0,#mermaid-svg-gIZkmNZC4ODV7ThQ .doneText1,#mermaid-svg-gIZkmNZC4ODV7ThQ .doneText2,#mermaid-svg-gIZkmNZC4ODV7ThQ .doneText3{fill:#000 !important}#mermaid-svg-gIZkmNZC4ODV7ThQ .crit0,#mermaid-svg-gIZkmNZC4ODV7ThQ .crit1,#mermaid-svg-gIZkmNZC4ODV7ThQ .crit2,#mermaid-svg-gIZkmNZC4ODV7ThQ .crit3{stroke:#f88;fill:red;stroke-width:2}#mermaid-svg-gIZkmNZC4ODV7ThQ .activeCrit0,#mermaid-svg-gIZkmNZC4ODV7ThQ .activeCrit1,#mermaid-svg-gIZkmNZC4ODV7ThQ .activeCrit2,#mermaid-svg-gIZkmNZC4ODV7ThQ .activeCrit3{stroke:#f88;fill:#bfc7ff;stroke-width:2}#mermaid-svg-gIZkmNZC4ODV7ThQ .doneCrit0,#mermaid-svg-gIZkmNZC4ODV7ThQ .doneCrit1,#mermaid-svg-gIZkmNZC4ODV7ThQ .doneCrit2,#mermaid-svg-gIZkmNZC4ODV7ThQ .doneCrit3{stroke:#f88;fill:#d3d3d3;stroke-width:2;cursor:pointer;shape-rendering:crispEdges}#mermaid-svg-gIZkmNZC4ODV7ThQ .milestone{transform:rotate(45deg) scale(0.8, 0.8)}#mermaid-svg-gIZkmNZC4ODV7ThQ .milestoneText{font-style:italic}#mermaid-svg-gIZkmNZC4ODV7ThQ .doneCritText0,#mermaid-svg-gIZkmNZC4ODV7ThQ .doneCritText1,#mermaid-svg-gIZkmNZC4ODV7ThQ .doneCritText2,#mermaid-svg-gIZkmNZC4ODV7ThQ .doneCritText3{fill:#000 !important}#mermaid-svg-gIZkmNZC4ODV7ThQ .activeCritText0,#mermaid-svg-gIZkmNZC4ODV7ThQ .activeCritText1,#mermaid-svg-gIZkmNZC4ODV7ThQ .activeCritText2,#mermaid-svg-gIZkmNZC4ODV7ThQ .activeCritText3{fill:#000 !important}#mermaid-svg-gIZkmNZC4ODV7ThQ .titleText{text-anchor:middle;font-size:18px;fill:#000;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-gIZkmNZC4ODV7ThQ g.classGroup text{fill:#9370db;stroke:none;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);font-size:10px}#mermaid-svg-gIZkmNZC4ODV7ThQ g.classGroup text .title{font-weight:bolder}#mermaid-svg-gIZkmNZC4ODV7ThQ g.clickable{cursor:pointer}#mermaid-svg-gIZkmNZC4ODV7ThQ g.classGroup rect{fill:#ECECFF;stroke:#9370db}#mermaid-svg-gIZkmNZC4ODV7ThQ g.classGroup line{stroke:#9370db;stroke-width:1}#mermaid-svg-gIZkmNZC4ODV7ThQ .classLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5}#mermaid-svg-gIZkmNZC4ODV7ThQ .classLabel .label{fill:#9370db;font-size:10px}#mermaid-svg-gIZkmNZC4ODV7ThQ .relation{stroke:#9370db;stroke-width:1;fill:none}#mermaid-svg-gIZkmNZC4ODV7ThQ .dashed-line{stroke-dasharray:3}#mermaid-svg-gIZkmNZC4ODV7ThQ #compositionStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-gIZkmNZC4ODV7ThQ #compositionEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-gIZkmNZC4ODV7ThQ #aggregationStart{fill:#ECECFF;stroke:#9370db;stroke-width:1}#mermaid-svg-gIZkmNZC4ODV7ThQ #aggregationEnd{fill:#ECECFF;stroke:#9370db;stroke-width:1}#mermaid-svg-gIZkmNZC4ODV7ThQ #dependencyStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-gIZkmNZC4ODV7ThQ #dependencyEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-gIZkmNZC4ODV7ThQ #extensionStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-gIZkmNZC4ODV7ThQ #extensionEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-gIZkmNZC4ODV7ThQ .commit-id,#mermaid-svg-gIZkmNZC4ODV7ThQ .commit-msg,#mermaid-svg-gIZkmNZC4ODV7ThQ .branch-label{fill:lightgrey;color:lightgrey;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-gIZkmNZC4ODV7ThQ .pieTitleText{text-anchor:middle;font-size:25px;fill:#000;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-gIZkmNZC4ODV7ThQ .slice{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-gIZkmNZC4ODV7ThQ g.stateGroup text{fill:#9370db;stroke:none;font-size:10px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-gIZkmNZC4ODV7ThQ g.stateGroup text{fill:#9370db;fill:#333;stroke:none;font-size:10px}#mermaid-svg-gIZkmNZC4ODV7ThQ g.statediagram-cluster .cluster-label text{fill:#333}#mermaid-svg-gIZkmNZC4ODV7ThQ g.stateGroup .state-title{font-weight:bolder;fill:#000}#mermaid-svg-gIZkmNZC4ODV7ThQ g.stateGroup rect{fill:#ECECFF;stroke:#9370db}#mermaid-svg-gIZkmNZC4ODV7ThQ g.stateGroup line{stroke:#9370db;stroke-width:1}#mermaid-svg-gIZkmNZC4ODV7ThQ .transition{stroke:#9370db;stroke-width:1;fill:none}#mermaid-svg-gIZkmNZC4ODV7ThQ .stateGroup .composit{fill:white;border-bottom:1px}#mermaid-svg-gIZkmNZC4ODV7ThQ .stateGroup .alt-composit{fill:#e0e0e0;border-bottom:1px}#mermaid-svg-gIZkmNZC4ODV7ThQ .state-note{stroke:#aa3;fill:#fff5ad}#mermaid-svg-gIZkmNZC4ODV7ThQ .state-note text{fill:black;stroke:none;font-size:10px}#mermaid-svg-gIZkmNZC4ODV7ThQ .stateLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.7}#mermaid-svg-gIZkmNZC4ODV7ThQ .edgeLabel text{fill:#333}#mermaid-svg-gIZkmNZC4ODV7ThQ .stateLabel text{fill:#000;font-size:10px;font-weight:bold;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-gIZkmNZC4ODV7ThQ .node circle.state-start{fill:black;stroke:black}#mermaid-svg-gIZkmNZC4ODV7ThQ .node circle.state-end{fill:black;stroke:white;stroke-width:1.5}#mermaid-svg-gIZkmNZC4ODV7ThQ #statediagram-barbEnd{fill:#9370db}#mermaid-svg-gIZkmNZC4ODV7ThQ .statediagram-cluster rect{fill:#ECECFF;stroke:#9370db;stroke-width:1px}#mermaid-svg-gIZkmNZC4ODV7ThQ .statediagram-cluster rect.outer{rx:5px;ry:5px}#mermaid-svg-gIZkmNZC4ODV7ThQ .statediagram-state .divider{stroke:#9370db}#mermaid-svg-gIZkmNZC4ODV7ThQ .statediagram-state .title-state{rx:5px;ry:5px}#mermaid-svg-gIZkmNZC4ODV7ThQ .statediagram-cluster.statediagram-cluster .inner{fill:white}#mermaid-svg-gIZkmNZC4ODV7ThQ .statediagram-cluster.statediagram-cluster-alt .inner{fill:#e0e0e0}#mermaid-svg-gIZkmNZC4ODV7ThQ .statediagram-cluster .inner{rx:0;ry:0}#mermaid-svg-gIZkmNZC4ODV7ThQ .statediagram-state rect.basic{rx:5px;ry:5px}#mermaid-svg-gIZkmNZC4ODV7ThQ .statediagram-state rect.divider{stroke-dasharray:10,10;fill:#efefef}#mermaid-svg-gIZkmNZC4ODV7ThQ .note-edge{stroke-dasharray:5}#mermaid-svg-gIZkmNZC4ODV7ThQ .statediagram-note rect{fill:#fff5ad;stroke:#aa3;stroke-width:1px;rx:0;ry:0}:root{--mermaid-font-family: '"trebuchet ms", verdana, arial';--mermaid-font-family: "Comic Sans MS", "Comic Sans", cursive}#mermaid-svg-gIZkmNZC4ODV7ThQ .error-icon{fill:#522}#mermaid-svg-gIZkmNZC4ODV7ThQ .error-text{fill:#522;stroke:#522}#mermaid-svg-gIZkmNZC4ODV7ThQ .edge-thickness-normal{stroke-width:2px}#mermaid-svg-gIZkmNZC4ODV7ThQ .edge-thickness-thick{stroke-width:3.5px}#mermaid-svg-gIZkmNZC4ODV7ThQ .edge-pattern-solid{stroke-dasharray:0}#mermaid-svg-gIZkmNZC4ODV7ThQ .edge-pattern-dashed{stroke-dasharray:3}#mermaid-svg-gIZkmNZC4ODV7ThQ .edge-pattern-dotted{stroke-dasharray:2}#mermaid-svg-gIZkmNZC4ODV7ThQ .marker{fill:#333}#mermaid-svg-gIZkmNZC4ODV7ThQ .marker.cross{stroke:#333}:root { --mermaid-font-family: "trebuchet ms", verdana, arial;}#mermaid-svg-gIZkmNZC4ODV7ThQ {color: rgba(0, 0, 0, 0.75);font: ;}

向左拖拽1px
笔触原点X坐标-1
清空整个画布
重新绘制并渲染
视觉效果向左移动1px

开发过程中修正节流参数的截图(未清空画布,未处理边界问题)

缩放

1-双指缩放绘制过程:

关键点
1、双指缩放使用ontouchmove判断并非ontouchstart;
说明:使用ontouchstart判断是否为双指,是通过接触点的数量是否为2确定的。但实际情况中我们很难两只手指在同一时刻接触到手机屏幕,所以我们改为判定在某一时刻中屏幕上同时有两个接触点即认为触发了双指缩放。
2、判断是缩还是放,并计算缩放中心点
3、确定一个适当的倍数差值后进行计算并移动笔触

计算过程:
放大1.5倍实现步骤

#mermaid-svg-87wLs7ekU5hU18bG .label{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);fill:#333;color:#333}#mermaid-svg-87wLs7ekU5hU18bG .label text{fill:#333}#mermaid-svg-87wLs7ekU5hU18bG .node rect,#mermaid-svg-87wLs7ekU5hU18bG .node circle,#mermaid-svg-87wLs7ekU5hU18bG .node ellipse,#mermaid-svg-87wLs7ekU5hU18bG .node polygon,#mermaid-svg-87wLs7ekU5hU18bG .node path{fill:#ECECFF;stroke:#9370db;stroke-width:1px}#mermaid-svg-87wLs7ekU5hU18bG .node .label{text-align:center;fill:#333}#mermaid-svg-87wLs7ekU5hU18bG .node.clickable{cursor:pointer}#mermaid-svg-87wLs7ekU5hU18bG .arrowheadPath{fill:#333}#mermaid-svg-87wLs7ekU5hU18bG .edgePath .path{stroke:#333;stroke-width:1.5px}#mermaid-svg-87wLs7ekU5hU18bG .flowchart-link{stroke:#333;fill:none}#mermaid-svg-87wLs7ekU5hU18bG .edgeLabel{background-color:#e8e8e8;text-align:center}#mermaid-svg-87wLs7ekU5hU18bG .edgeLabel rect{opacity:0.9}#mermaid-svg-87wLs7ekU5hU18bG .edgeLabel span{color:#333}#mermaid-svg-87wLs7ekU5hU18bG .cluster rect{fill:#ffffde;stroke:#aa3;stroke-width:1px}#mermaid-svg-87wLs7ekU5hU18bG .cluster text{fill:#333}#mermaid-svg-87wLs7ekU5hU18bG div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);font-size:12px;background:#ffffde;border:1px solid #aa3;border-radius:2px;pointer-events:none;z-index:100}#mermaid-svg-87wLs7ekU5hU18bG .actor{stroke:#ccf;fill:#ECECFF}#mermaid-svg-87wLs7ekU5hU18bG text.actor>tspan{fill:#000;stroke:none}#mermaid-svg-87wLs7ekU5hU18bG .actor-line{stroke:grey}#mermaid-svg-87wLs7ekU5hU18bG .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333}#mermaid-svg-87wLs7ekU5hU18bG .messageLine1{stroke-width:1.5;stroke-dasharray:2, 2;stroke:#333}#mermaid-svg-87wLs7ekU5hU18bG #arrowhead path{fill:#333;stroke:#333}#mermaid-svg-87wLs7ekU5hU18bG .sequenceNumber{fill:#fff}#mermaid-svg-87wLs7ekU5hU18bG #sequencenumber{fill:#333}#mermaid-svg-87wLs7ekU5hU18bG #crosshead path{fill:#333;stroke:#333}#mermaid-svg-87wLs7ekU5hU18bG .messageText{fill:#333;stroke:#333}#mermaid-svg-87wLs7ekU5hU18bG .labelBox{stroke:#ccf;fill:#ECECFF}#mermaid-svg-87wLs7ekU5hU18bG .labelText,#mermaid-svg-87wLs7ekU5hU18bG .labelText>tspan{fill:#000;stroke:none}#mermaid-svg-87wLs7ekU5hU18bG .loopText,#mermaid-svg-87wLs7ekU5hU18bG .loopText>tspan{fill:#000;stroke:none}#mermaid-svg-87wLs7ekU5hU18bG .loopLine{stroke-width:2px;stroke-dasharray:2, 2;stroke:#ccf;fill:#ccf}#mermaid-svg-87wLs7ekU5hU18bG .note{stroke:#aa3;fill:#fff5ad}#mermaid-svg-87wLs7ekU5hU18bG .noteText,#mermaid-svg-87wLs7ekU5hU18bG .noteText>tspan{fill:#000;stroke:none}#mermaid-svg-87wLs7ekU5hU18bG .activation0{fill:#f4f4f4;stroke:#666}#mermaid-svg-87wLs7ekU5hU18bG .activation1{fill:#f4f4f4;stroke:#666}#mermaid-svg-87wLs7ekU5hU18bG .activation2{fill:#f4f4f4;stroke:#666}#mermaid-svg-87wLs7ekU5hU18bG .mermaid-main-font{font-family:"trebuchet ms", verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-87wLs7ekU5hU18bG .section{stroke:none;opacity:0.2}#mermaid-svg-87wLs7ekU5hU18bG .section0{fill:rgba(102,102,255,0.49)}#mermaid-svg-87wLs7ekU5hU18bG .section2{fill:#fff400}#mermaid-svg-87wLs7ekU5hU18bG .section1,#mermaid-svg-87wLs7ekU5hU18bG .section3{fill:#fff;opacity:0.2}#mermaid-svg-87wLs7ekU5hU18bG .sectionTitle0{fill:#333}#mermaid-svg-87wLs7ekU5hU18bG .sectionTitle1{fill:#333}#mermaid-svg-87wLs7ekU5hU18bG .sectionTitle2{fill:#333}#mermaid-svg-87wLs7ekU5hU18bG .sectionTitle3{fill:#333}#mermaid-svg-87wLs7ekU5hU18bG .sectionTitle{text-anchor:start;font-size:11px;text-height:14px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-87wLs7ekU5hU18bG .grid .tick{stroke:#d3d3d3;opacity:0.8;shape-rendering:crispEdges}#mermaid-svg-87wLs7ekU5hU18bG .grid .tick text{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-87wLs7ekU5hU18bG .grid path{stroke-width:0}#mermaid-svg-87wLs7ekU5hU18bG .today{fill:none;stroke:red;stroke-width:2px}#mermaid-svg-87wLs7ekU5hU18bG .task{stroke-width:2}#mermaid-svg-87wLs7ekU5hU18bG .taskText{text-anchor:middle;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-87wLs7ekU5hU18bG .taskText:not([font-size]){font-size:11px}#mermaid-svg-87wLs7ekU5hU18bG .taskTextOutsideRight{fill:#000;text-anchor:start;font-size:11px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-87wLs7ekU5hU18bG .taskTextOutsideLeft{fill:#000;text-anchor:end;font-size:11px}#mermaid-svg-87wLs7ekU5hU18bG .task.clickable{cursor:pointer}#mermaid-svg-87wLs7ekU5hU18bG .taskText.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-87wLs7ekU5hU18bG .taskTextOutsideLeft.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-87wLs7ekU5hU18bG .taskTextOutsideRight.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-87wLs7ekU5hU18bG .taskText0,#mermaid-svg-87wLs7ekU5hU18bG .taskText1,#mermaid-svg-87wLs7ekU5hU18bG .taskText2,#mermaid-svg-87wLs7ekU5hU18bG .taskText3{fill:#fff}#mermaid-svg-87wLs7ekU5hU18bG .task0,#mermaid-svg-87wLs7ekU5hU18bG .task1,#mermaid-svg-87wLs7ekU5hU18bG .task2,#mermaid-svg-87wLs7ekU5hU18bG .task3{fill:#8a90dd;stroke:#534fbc}#mermaid-svg-87wLs7ekU5hU18bG .taskTextOutside0,#mermaid-svg-87wLs7ekU5hU18bG .taskTextOutside2{fill:#000}#mermaid-svg-87wLs7ekU5hU18bG .taskTextOutside1,#mermaid-svg-87wLs7ekU5hU18bG .taskTextOutside3{fill:#000}#mermaid-svg-87wLs7ekU5hU18bG .active0,#mermaid-svg-87wLs7ekU5hU18bG .active1,#mermaid-svg-87wLs7ekU5hU18bG .active2,#mermaid-svg-87wLs7ekU5hU18bG .active3{fill:#bfc7ff;stroke:#534fbc}#mermaid-svg-87wLs7ekU5hU18bG .activeText0,#mermaid-svg-87wLs7ekU5hU18bG .activeText1,#mermaid-svg-87wLs7ekU5hU18bG .activeText2,#mermaid-svg-87wLs7ekU5hU18bG .activeText3{fill:#000 !important}#mermaid-svg-87wLs7ekU5hU18bG .done0,#mermaid-svg-87wLs7ekU5hU18bG .done1,#mermaid-svg-87wLs7ekU5hU18bG .done2,#mermaid-svg-87wLs7ekU5hU18bG .done3{stroke:grey;fill:#d3d3d3;stroke-width:2}#mermaid-svg-87wLs7ekU5hU18bG .doneText0,#mermaid-svg-87wLs7ekU5hU18bG .doneText1,#mermaid-svg-87wLs7ekU5hU18bG .doneText2,#mermaid-svg-87wLs7ekU5hU18bG .doneText3{fill:#000 !important}#mermaid-svg-87wLs7ekU5hU18bG .crit0,#mermaid-svg-87wLs7ekU5hU18bG .crit1,#mermaid-svg-87wLs7ekU5hU18bG .crit2,#mermaid-svg-87wLs7ekU5hU18bG .crit3{stroke:#f88;fill:red;stroke-width:2}#mermaid-svg-87wLs7ekU5hU18bG .activeCrit0,#mermaid-svg-87wLs7ekU5hU18bG .activeCrit1,#mermaid-svg-87wLs7ekU5hU18bG .activeCrit2,#mermaid-svg-87wLs7ekU5hU18bG .activeCrit3{stroke:#f88;fill:#bfc7ff;stroke-width:2}#mermaid-svg-87wLs7ekU5hU18bG .doneCrit0,#mermaid-svg-87wLs7ekU5hU18bG .doneCrit1,#mermaid-svg-87wLs7ekU5hU18bG .doneCrit2,#mermaid-svg-87wLs7ekU5hU18bG .doneCrit3{stroke:#f88;fill:#d3d3d3;stroke-width:2;cursor:pointer;shape-rendering:crispEdges}#mermaid-svg-87wLs7ekU5hU18bG .milestone{transform:rotate(45deg) scale(0.8, 0.8)}#mermaid-svg-87wLs7ekU5hU18bG .milestoneText{font-style:italic}#mermaid-svg-87wLs7ekU5hU18bG .doneCritText0,#mermaid-svg-87wLs7ekU5hU18bG .doneCritText1,#mermaid-svg-87wLs7ekU5hU18bG .doneCritText2,#mermaid-svg-87wLs7ekU5hU18bG .doneCritText3{fill:#000 !important}#mermaid-svg-87wLs7ekU5hU18bG .activeCritText0,#mermaid-svg-87wLs7ekU5hU18bG .activeCritText1,#mermaid-svg-87wLs7ekU5hU18bG .activeCritText2,#mermaid-svg-87wLs7ekU5hU18bG .activeCritText3{fill:#000 !important}#mermaid-svg-87wLs7ekU5hU18bG .titleText{text-anchor:middle;font-size:18px;fill:#000;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-87wLs7ekU5hU18bG g.classGroup text{fill:#9370db;stroke:none;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);font-size:10px}#mermaid-svg-87wLs7ekU5hU18bG g.classGroup text .title{font-weight:bolder}#mermaid-svg-87wLs7ekU5hU18bG g.clickable{cursor:pointer}#mermaid-svg-87wLs7ekU5hU18bG g.classGroup rect{fill:#ECECFF;stroke:#9370db}#mermaid-svg-87wLs7ekU5hU18bG g.classGroup line{stroke:#9370db;stroke-width:1}#mermaid-svg-87wLs7ekU5hU18bG .classLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5}#mermaid-svg-87wLs7ekU5hU18bG .classLabel .label{fill:#9370db;font-size:10px}#mermaid-svg-87wLs7ekU5hU18bG .relation{stroke:#9370db;stroke-width:1;fill:none}#mermaid-svg-87wLs7ekU5hU18bG .dashed-line{stroke-dasharray:3}#mermaid-svg-87wLs7ekU5hU18bG #compositionStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-87wLs7ekU5hU18bG #compositionEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-87wLs7ekU5hU18bG #aggregationStart{fill:#ECECFF;stroke:#9370db;stroke-width:1}#mermaid-svg-87wLs7ekU5hU18bG #aggregationEnd{fill:#ECECFF;stroke:#9370db;stroke-width:1}#mermaid-svg-87wLs7ekU5hU18bG #dependencyStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-87wLs7ekU5hU18bG #dependencyEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-87wLs7ekU5hU18bG #extensionStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-87wLs7ekU5hU18bG #extensionEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-87wLs7ekU5hU18bG .commit-id,#mermaid-svg-87wLs7ekU5hU18bG .commit-msg,#mermaid-svg-87wLs7ekU5hU18bG .branch-label{fill:lightgrey;color:lightgrey;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-87wLs7ekU5hU18bG .pieTitleText{text-anchor:middle;font-size:25px;fill:#000;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-87wLs7ekU5hU18bG .slice{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-87wLs7ekU5hU18bG g.stateGroup text{fill:#9370db;stroke:none;font-size:10px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-87wLs7ekU5hU18bG g.stateGroup text{fill:#9370db;fill:#333;stroke:none;font-size:10px}#mermaid-svg-87wLs7ekU5hU18bG g.statediagram-cluster .cluster-label text{fill:#333}#mermaid-svg-87wLs7ekU5hU18bG g.stateGroup .state-title{font-weight:bolder;fill:#000}#mermaid-svg-87wLs7ekU5hU18bG g.stateGroup rect{fill:#ECECFF;stroke:#9370db}#mermaid-svg-87wLs7ekU5hU18bG g.stateGroup line{stroke:#9370db;stroke-width:1}#mermaid-svg-87wLs7ekU5hU18bG .transition{stroke:#9370db;stroke-width:1;fill:none}#mermaid-svg-87wLs7ekU5hU18bG .stateGroup .composit{fill:white;border-bottom:1px}#mermaid-svg-87wLs7ekU5hU18bG .stateGroup .alt-composit{fill:#e0e0e0;border-bottom:1px}#mermaid-svg-87wLs7ekU5hU18bG .state-note{stroke:#aa3;fill:#fff5ad}#mermaid-svg-87wLs7ekU5hU18bG .state-note text{fill:black;stroke:none;font-size:10px}#mermaid-svg-87wLs7ekU5hU18bG .stateLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.7}#mermaid-svg-87wLs7ekU5hU18bG .edgeLabel text{fill:#333}#mermaid-svg-87wLs7ekU5hU18bG .stateLabel text{fill:#000;font-size:10px;font-weight:bold;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-87wLs7ekU5hU18bG .node circle.state-start{fill:black;stroke:black}#mermaid-svg-87wLs7ekU5hU18bG .node circle.state-end{fill:black;stroke:white;stroke-width:1.5}#mermaid-svg-87wLs7ekU5hU18bG #statediagram-barbEnd{fill:#9370db}#mermaid-svg-87wLs7ekU5hU18bG .statediagram-cluster rect{fill:#ECECFF;stroke:#9370db;stroke-width:1px}#mermaid-svg-87wLs7ekU5hU18bG .statediagram-cluster rect.outer{rx:5px;ry:5px}#mermaid-svg-87wLs7ekU5hU18bG .statediagram-state .divider{stroke:#9370db}#mermaid-svg-87wLs7ekU5hU18bG .statediagram-state .title-state{rx:5px;ry:5px}#mermaid-svg-87wLs7ekU5hU18bG .statediagram-cluster.statediagram-cluster .inner{fill:white}#mermaid-svg-87wLs7ekU5hU18bG .statediagram-cluster.statediagram-cluster-alt .inner{fill:#e0e0e0}#mermaid-svg-87wLs7ekU5hU18bG .statediagram-cluster .inner{rx:0;ry:0}#mermaid-svg-87wLs7ekU5hU18bG .statediagram-state rect.basic{rx:5px;ry:5px}#mermaid-svg-87wLs7ekU5hU18bG .statediagram-state rect.divider{stroke-dasharray:10,10;fill:#efefef}#mermaid-svg-87wLs7ekU5hU18bG .note-edge{stroke-dasharray:5}#mermaid-svg-87wLs7ekU5hU18bG .statediagram-note rect{fill:#fff5ad;stroke:#aa3;stroke-width:1px;rx:0;ry:0}:root{--mermaid-font-family: '"trebuchet ms", verdana, arial';--mermaid-font-family: "Comic Sans MS", "Comic Sans", cursive}#mermaid-svg-87wLs7ekU5hU18bG .error-icon{fill:#522}#mermaid-svg-87wLs7ekU5hU18bG .error-text{fill:#522;stroke:#522}#mermaid-svg-87wLs7ekU5hU18bG .edge-thickness-normal{stroke-width:2px}#mermaid-svg-87wLs7ekU5hU18bG .edge-thickness-thick{stroke-width:3.5px}#mermaid-svg-87wLs7ekU5hU18bG .edge-pattern-solid{stroke-dasharray:0}#mermaid-svg-87wLs7ekU5hU18bG .edge-pattern-dashed{stroke-dasharray:3}#mermaid-svg-87wLs7ekU5hU18bG .edge-pattern-dotted{stroke-dasharray:2}#mermaid-svg-87wLs7ekU5hU18bG .marker{fill:#333}#mermaid-svg-87wLs7ekU5hU18bG .marker.cross{stroke:#333}:root { --mermaid-font-family: "trebuchet ms", verdana, arial;}#mermaid-svg-87wLs7ekU5hU18bG {color: rgba(0, 0, 0, 0.75);font: ;}

感知到屏幕上两个触点的位置
确定缩放中心点坐标
确定放大1.5倍后对应缩放中心点的坐标
计算缩放前后中心点坐标的偏移量
清空整个画布
重新放大1.5倍后绘制并渲染
视觉效果放大1.5倍

1)获取到屏幕两个接触点的坐标后,计算缩放中心点和两点距离。
举例:触点1坐标(a,b),触点2坐标(c,d),
缩放中心点坐标(x1,x2):
x1=(a+c)/2x1= (a+c)/2x1=(a+c)/2x2=(b+d)/2x2= (b+d)/2x2=(b+d)/2

两点距离:d2=(a−c)2+(b−d)2d^2= (a-c)^2+(b-d)^2d2=(a−c)2+(b−d)2

2)通过d的实时变化进行缩放,一开始的距离/现在的距离=应该缩放的比例,

3)将视窗的缩放中心点对应到画布上,计算缩放后画布的偏移距离,将笔触原点反向移动相应的偏移距离后,再次将画布的缩放中心点和视窗的缩放中心点对应上,即可实现按照中心点缩放
简单理解:

如上图所示,A(x,y)点是缩放中心,放大n倍后对应的点跑到了A1(x1,y1),要想保证缩放的中心点看起来位置不动,我们需要将A1点移动到A点,即偏移(x1-x,y1-y)的距离

实际实现:
实际中我们需要把视窗考虑进去,因为我们能获取到的缩放中心点都是相对于手机屏幕来说的,我们需要把这个位置对应到画布上(当前缩放倍数下的单位距离和当前视窗的单位距离不一致),但画布的缩放移动又完全不影响视窗,所以我们需要维护两套坐标系。最终需要确定的偏移量为:每次缩放之后的图像相对于初始大小下初始位置的偏移值
具体代码:

// 先缩放再位移const translateX =((((x - this.lastTransform.x * this.lastTransform.scale) / this.lastTransform.scale) * scale -x) /scale) *-1;const translateY =((((y - this.lastTransform.y * this.lastTransform.scale) / this.lastTransform.scale) * scale -y) /scale) *-1;

解释说明:
(本次屏幕缩放中心点-之前的偏移值*之前的倍数)/倍数=相对于初始大小下的具体坐标

(初始大小下的坐标*新要缩放的倍数-屏幕缩放中心)/新要缩放的倍数=新要偏移的值(相对于最初始的位置)

4)进行绘制

 ctx.scale(this.newTransform.scale, this.newTransform.scale);ctx.translate(this.newTransform.x, this.newTransform.y);ctx.drawImage(this.image, 0, 0);

注意要先缩放后移动,canvas缩放的原理是把整个坐标轴的距离拉长,但坐标不变,这也是为什么我们最终每次要求的偏移量是相对初始大小来说的

5)处理边界情况
设定一个最小的缩放值和一个最大的缩放值,以及校验偏移量。确定画布永远把视窗包含在其中(页面中不会留白)

2-星星的展示:
1)反缩放
因为我们整个星图使用的是canvas,所以星星的反缩放就比较容易实现,在绘制下一帧之前我们已经拿到了画布的缩放比例,只需要告诉绘制星星的这个笔触进行反比例的放大和缩小就行了。

2)隐藏
因为星星不会跟随星空缩放,防止视觉区域内星星过于密集,星图要求在较小的倍率下隐藏一部分较小的星星。处理方式:在缩放到临界倍数的下一帧时,读取配置文件中的设计同学精心计算好要隐藏的星座坐标,控制相应坐标的笔触忽略本次星星的绘制。只是不展示了,但他依然真实在星空上存在。

3)点击
不同于传统的dom可以直接在相应的元素上绑定事件,canvas每一帧绘制完成的结果本质上是张图片。所以我们获取到屏幕上的点击位置后,也要将其转换为画布上的坐标(又用到了我们之前维护的画布和视窗相转换的坐标系)。获取到画布上的坐标后,遍历所有星星的坐标和其附近相应的热区,匹配上之后即认为我们点击的是这颗星星。同时我们也能处理即使是当前缩放倍率下未展示的星星,我们依然可以定位到他的位置。

部分优化细节

1)渲染频率优化
在拖拽和缩放实现过程中,我们描述的只是其中一帧的绘制过程,比如放大1.5倍实际的实现不可能从1直接到1.5,因为这样会显的很突兀,和用户的交互非常不友好。真实情况下可能是1->1.01 甚至1.001,当然每次的变更值越小,展示出来的效果越流畅。但每次的变化都要经历确定缩放中心,计算偏移量…等一系列过程,对手机的cpu和gpu性能是一大考验尤其是低端机型会明显感觉到卡顿。所以我们既要保证缩放效果的流畅,又要尽可能的降低计算频率,我采用对通过requestAnimationFrame控制缩放的触发频率和画面的刷新频率保持一致(60HZ,部分手机可能不一致)来平衡这两点。

2)星星的动效优化
因为星星的数量较多且动效全部采用svga资源进行绘制,为了节省开销,相同等级之间的星星均采用同一svga资源,并保持相同的动画频率。

最终效果:

以上是实现的大致过程,因为想解释的尽量能让我这样的菜狗看懂所以有些啰嗦,还望各位大佬多担待。如果有类似开发需求的同学欢迎一起探讨和交流。

canvas模拟实现高德地图的部分功能相关推荐

  1. Android学习之高德地图的通用功能开发步骤(二)

    周一又来了,我就接着上次的开发步骤(一)来吧,继续把高德地图的相关简单功能分享一下 上次写到了第六步,接着写第七步吧. 第七步:定位 + 地图选点 + 路径规划 + 实时导航 以下是我的这个功能Nav ...

  2. 利用高德地图实现定位功能

    最近学习使用高德地图可谓是出师不利....嘛,不知道为啥高德给的3d地图的jar包用不了,最后实在没办法用了2d的jar包,然后在大佬和其他资料的帮助下,实现了高德地图的定位功能.接下来就说一下具体的 ...

  3. 高德地图轨迹回放功能

    一.介绍        在项目过程中,需要对自己设备产品输出的定位信息进行验证.通过路跑测试获取到了一组经纬度数据.这时需要验证这组数据是否是实际路跑测试的轨迹,就用到了高德地图的轨迹回放功能.下面将 ...

  4. 高德地图小蓝点_一会晴天一会下雨?夏日想要顺利出行 高德地图这些小功能最实用...

    不同于其他三个季节,夏天总是有很多种烦恼,变化不定的天气就是其中最为影响出行的一项因素.而面对忽晴忽雨的天气,如何才能在夏日顺利出行呢?看看高德地图的这些实用小功能吧. ·实时天气预报 高德地图可以实 ...

  5. 高德地图JSAPI测距功能优化

    文章目录 前言 测距实现思路 使用测距插件 开启测距 关闭测距 前言 高德提供了一个距离测量插件可直接使用,但是没有完全满足需求.在测距过程中只会显示新增节点到起始点的总长度,而不会在鼠标移动过程中显 ...

  6. 高德地图我的队伍查岗_高德地图查岗新功能 让你的行踪无所遁形

    如果平时家里有行动不便的老人或年幼的孩子,在他们独自外出的时候,咱们总会担惊受怕. 特别是有些老人因为太过年迈,不仅行动方便,还患有老年痴呆症,如果偷偷跑出去找不到人就麻烦了. 家人地图 于是在7月1 ...

  7. 安卓系统的导航仪怎么设置导航启动路径为高德地图_界面功能焕然一新!高德地图10.0新版体验...

    [PConline应用]近日高德地图10.0安卓版与iOS版同时上线,作为一名资深高德迷,我自然第一时间下载并更新了它.没让我失望的是,此次新版不但用上了全新的扁平式UI,各项功能模块也有了大幅进步, ...

  8. 高德地图 点聚合功能(Adnroid)

    1.需求: 接下来的项目要实现像链家APP中地图看房的功能(效果如下图). 2.实现思路.查阅资料 看到这个效果图,首先想到的是在view上放一个marker,但是marker只能设置title,没有 ...

  9. 高德地图聚合点删除_高德地图 点聚合功能(Adnroid)

    1.需求: 接下来的项目要实现像链家APP中地图看房的功能(效果如下图). 链家APP地图找房效果 2.实现思路.查阅资料 看到这个效果图,首先想到的是在view上放一个marker,但是marker ...

  10. 高德地图的自动定位功能

    1.去高德地图开放平台去注册,获得自独一无二的key值 <script type="text/javascript" src="https://webapi.ama ...

最新文章

  1. 测试类异常Manual close is not allowed over a Spring managed SqlSession
  2. NGUI 使用Grid自动排列UI
  3. leetcode 263, 264, 1201, 313. Ugly Number I, II, III, Super Ugly Number(leetcode 丑数问题合集)
  4. 恢复二叉搜索树Python解法
  5. AgileConfig轻量级配置中心1.4.0发布,重构了发布功能
  6. C# 对程序窗口进程和进程ID
  7. 启动NameNode和DataNode
  8. 自定义WPF ListBox的选择样式
  9. python金融衍生品_《Python金融衍生品大数据分析:建模、模拟、校准与对冲(博文视点出品)》【摘要 书评 试读】- 京东图书...
  10. 创建向导时为其添加path,指为jar添加到path里面
  11. 冗余链路中STP协议的工作过程以及二期STP收敛速度优化方案介绍
  12. “自由软件”已过时?
  13. 大牛的面试感悟(转) 没事多看看解决人生困惑!
  14. 使用小米手机进行真机测试
  15. maven中的ArtifactId和groupId是什么
  16. 【SpringBoot2—junit5断言、前置条件】
  17. C++学习(三十九)(C语言部分)之 游戏项目(2048游戏)
  18. python 算法教程 pdf 英文_上手实践《Python机器学习第2版》PDF中文+PDF英文+代码+Sebastian...
  19. 华为手机像素密度排行_虽然华为Mate20 X的像素密度更低,但它清晰度不如Mate20吗?...
  20. 查看和修改电脑的ip地址

热门文章

  1. google地址栏的代码是什么意思(转)
  2. 详解原生JS实现走马灯轮播图
  3. 猜图达人小游戏V4.1小程序源码可开流量主
  4. SimpleMind 1.27.1 小巧的思维导图工具
  5. Jquery识别银行卡号码是否正确
  6. 公众号第三方平台开发 教程五 代公众号处理消息和事件
  7. D3D9利用顶点缓冲区绘制三角形
  8. d3d透视逆向篇:第8课 通过虚表函数的获取D3D9函数指针
  9. ESXi服务器遇到 IPMI_SI_DRV 的解决, 感谢原作者 以及今天 解决问题.
  10. 中企海外周报 | 哈弗F7x性能版在俄罗斯上市;徐工首家海外银行落户巴西