基于 HTML5 Canvas 的可交互旋钮组件
<h2>前言</h2><p>此次的 <span style="font-family: "times new roman", times">Demo</span> 效果如下:</p>
<p><img src="https://img2018.cnblogs.com/blog/1496396/201907/1496396-20190728133149212-1911661542.gif"></p>
<p>Demo 链接:<span style="font-family: "times new roman", times">https://hightopo.com/demo/comp-knob/</span></p>
<h2><span style="font-family: "times new roman", times">整体思路</span></h2>
<ul>
<li><span style="font-family: "times new roman", times">组件参数</span></li>
<li><span style="font-family: "times new roman", times">绘制旋钮</span></li>
<li><span style="font-family: "times new roman", times">绘制刻度</span></li>
<li><span style="font-family: "times new roman", times">绘制指针</span></li>
<li><span style="font-family: "times new roman", times">绘制标尺</span></li>
<li><span style="font-family: "times new roman", times">绘制文本</span></li>
<li><span style="font-family: "times new roman", times">交互效果</span></li>
</ul>
<h2><span style="font-family: "times new roman", times">1.组件参数</span></h2>
<p><span style="font-family: "times new roman", times"><img src="https://img2018.cnblogs.com/blog/1496396/201907/1496396-20190728130322711-1136222518.jpg"></span></p>
<p> </p>
<p>以下是下文会使用到的部分变量,在此先贴出来</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">var</span> origin, <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 原点</span>
percent, <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 显示刻度占总刻度的百分比</span>
partAngle, <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 每个刻度所占的角度</span>
startAngle, <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">刻度起始的角度</span>
calibrationPoints, <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 每个刻度的信息</span>
pointer, <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 指针的信息</span>
scaleLine, <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 标尺的信息</span>
calibrationColors <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 刻度渐变色</span></pre>
</div>
<h2>2.绘制旋钮</h2>
<p>这里主要就使用了 <span style="font-family: "times new roman", times">canvas api</span> 中的<span style="font-family: "times new roman", times"> arc()</span> 和 <span style="font-family: "times new roman", times">createRadialGradient()</span> 。</p>
<p>主要代码:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">g.beginPath();
</span><span style="color: rgba(0, 0, 255, 1)">var</span> ringRadial = g.createRadialGradient(origin.x, origin.y, <span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">, origin.x, origin.y, ringRadio);
ringRadial.addColorStop(</span><span style="color: rgba(128, 0, 128, 1)">0</span>, ht.Default.brighter(ringColor, <span style="color: rgba(128, 0, 128, 1)">20</span><span style="color: rgba(0, 0, 0, 1)">));
ringRadial.addColorStop(</span><span style="color: rgba(128, 0, 128, 1)">0.95</span>, ht.Default.brighter(ringColor, <span style="color: rgba(128, 0, 128, 1)">40</span><span style="color: rgba(0, 0, 0, 1)">));
ringRadial.addColorStop(</span><span style="color: rgba(128, 0, 128, 1)">1</span>, ht.Default.darker(ringColor, <span style="color: rgba(128, 0, 128, 1)">20</span><span style="color: rgba(0, 0, 0, 1)">));
</span><span style="color: rgba(0, 0, 255, 1)">var</span> borderRadial = g.createRadialGradient(origin.x, origin.y, ringRadio - ringBorderWidth / <span style="color: rgba(128, 0, 128, 1)">2</span>, origin.x, origin.y, ringRadio + ringBorderWidth / <span style="color: rgba(128, 0, 128, 1)">2</span><span style="color: rgba(0, 0, 0, 1)">);
borderRadial.addColorStop(</span><span style="color: rgba(128, 0, 128, 1)">0</span>, ht.Default.brighter(ringBorderColor, <span style="color: rgba(128, 0, 128, 1)">2</span><span style="color: rgba(0, 0, 0, 1)">));
borderRadial.addColorStop(</span><span style="color: rgba(128, 0, 128, 1)">0.5</span>, ht.Default.brighter(ringBorderColor, <span style="color: rgba(128, 0, 128, 1)">4</span><span style="color: rgba(0, 0, 0, 1)">));
borderRadial.addColorStop(</span><span style="color: rgba(128, 0, 128, 1)">1</span>, ht.Default.darker(ringBorderColor, <span style="color: rgba(128, 0, 128, 1)">4</span><span style="color: rgba(0, 0, 0, 1)">));
g.fillStyle </span>=<span style="color: rgba(0, 0, 0, 1)"> ringRadial;
g.lineWidth </span>=<span style="color: rgba(0, 0, 0, 1)"> ringBorderWidth;
g.strokeStyle </span>=<span style="color: rgba(0, 0, 0, 1)"> borderRadial;
g.arc(origin.x, origin.y, ringRadio, </span><span style="color: rgba(128, 0, 128, 1)">0</span>, <span style="color: rgba(128, 0, 128, 1)">2</span> *<span style="color: rgba(0, 0, 0, 1)"> Math.PI);
g.closePath();
g.fill();
g.stroke();</span></pre>
</div>
<p>效果图:</p>
<p><img src="https://img2018.cnblogs.com/blog/1496396/201907/1496396-20190728130849670-1071720891.jpg"></p>
<h2>3.绘制刻度</h2>
<p>这里绘制每个刻度采用的是绘制路径的方法,所以声明了一个变量 <span style="font-family: "times new roman", times">calibrationPoints</span> 用来存放每个刻度的起始点坐标,根据配置的参数去计算 <span style="font-family: "times new roman", times">calibrationPoints</span> 的信息。</p>
<p>首先根据参数 <span style="font-family: "times new roman", times">calibrationPercent</span> 计算第一个刻度的起始角度 <span style="font-family: "times new roman", times">startAngle</span> ,然后根绝 <span style="font-family: "times new roman", times">calibrationCount</span> 的值去计算每个刻度所占用的角度 <span style="font-family: "times new roman", times">partAngle</span> ,最后根据三角函数和相应的角度,转化为对应的坐标。</p>
<p>主要代码:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">var</span> calibrationPoints =<span style="color: rgba(0, 0, 0, 1)"> [];
</span><span style="color: rgba(0, 0, 255, 1)">for</span> (<span style="color: rgba(0, 0, 255, 1)">var</span> i = <span style="color: rgba(128, 0, 128, 1)">0</span>; i < calibrationCount + <span style="color: rgba(128, 0, 128, 1)">1</span>; i++<span style="color: rgba(0, 0, 0, 1)">) {
</span><span style="color: rgba(0, 0, 255, 1)">var</span> point =<span style="color: rgba(0, 0, 0, 1)"> {
startx: origin.x </span>+ (ringRadio + ringBorderWidth + <span style="color: rgba(128, 0, 128, 1)">0</span> * calibrationHeight) * Math.cos(startAngle - i *<span style="color: rgba(0, 0, 0, 1)"> partAngle),
starty: origin.y </span>- (ringRadio + ringBorderWidth + <span style="color: rgba(128, 0, 128, 1)">0</span> * calibrationHeight) * Math.sin(startAngle - i *<span style="color: rgba(0, 0, 0, 1)"> partAngle),
endx: origin.x </span>+ (ringRadio + ringBorderWidth + <span style="color: rgba(128, 0, 128, 1)">1</span> * calibrationHeight) * Math.cos(startAngle - i *<span style="color: rgba(0, 0, 0, 1)"> partAngle),
endy: origin.y </span>- (ringRadio + ringBorderWidth + <span style="color: rgba(128, 0, 128, 1)">1</span> * calibrationHeight) * Math.sin(startAngle - i *<span style="color: rgba(0, 0, 0, 1)"> partAngle)
};
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (i <= (calibrationCount * percent) && percent > <span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">) {
point.show </span>= <span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">;
} </span><span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)"> {
point.show </span>= <span style="color: rgba(0, 0, 255, 1)">false</span><span style="color: rgba(0, 0, 0, 1)">;
}
calibrationPoints.push(point);
}</span></pre>
</div>
<p>有了每个刻度的信息后,接下来就开始绘制刻度。</p>
<p> </p>
<p>主要代码:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">calibrationPoints.forEach(function (i, index) {
g.beginPath();
</span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (calibrationColorWheelShow) {
calibrationBrightColor </span>=<span style="color: rgba(0, 0, 0, 1)"> calibrationColors;
}
g.lineWidth </span>= <span style="color: rgba(128, 0, 128, 1)">1.2</span> *<span style="color: rgba(0, 0, 0, 1)"> calibrationWidth;
g.strokeStyle </span>= i.show ? calibrationBrightColor : ht.Default.brighter(calibrationDarkColor, <span style="color: rgba(128, 0, 128, 1)">10</span><span style="color: rgba(0, 0, 0, 1)">);
g.moveTo(i.startx, i.starty);
g.lineTo(i.endx, i.endy);
g.closePath();
g.stroke();
})
calibrationPoints.forEach(function (i, index) {
g.beginPath();
</span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (calibrationColorWheelShow) {
calibrationBrightColor </span>=<span style="color: rgba(0, 0, 0, 1)"> calibrationColors;
}
g.lineWidth </span>=<span style="color: rgba(0, 0, 0, 1)"> calibrationWidth;
g.strokeStyle </span>= i.show ?<span style="color: rgba(0, 0, 0, 1)"> calibrationBrightColor : calibrationDarkColor;
g.moveTo(i.startx, i.starty);
g.lineTo(i.endx, i.endy);
g.closePath();
g.stroke();
})</span></pre>
</div>
<p>效果图:</p>
<p><img src="https://img2018.cnblogs.com/blog/1496396/201907/1496396-20190728131612240-843632813.jpg"></p>
<p>考虑到一种高亮颜色太单调,于是加了个色轮。思路:给每个刻度都添加了颜色的标识。<br>每个刻度的颜色计算方法:把颜色值转换成 <span style="font-family: "times new roman", times">rgb</span> 方式,设定多少秒改变完成,每次改变多少值,计算需要多少次,比如<span style="font-family: "times new roman", times"> rba(x,y,z)</span> 到 <span style="font-family: "times new roman", times">rgb(a,b,c)</span>,假设需要 <span style="font-family: "times new roman", times">100</span> 次,那么每次设定 <span style="font-family: "times new roman", times">rgb((a - x) / 100 + x, (b - y) / 100 + y, (c - z) / 100 + z)</span> 。</p>
<p>主要代码:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">if</span> (calibrationColorWheelShow) { <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 显示刻度色轮</span>
<span style="color: rgba(0, 0, 255, 1)">var</span> colors =<span style="color: rgba(0, 0, 0, 1)"> [];
calibrationColorWheel.forEach(function (i) {
colors.push(ht.Default.toColorData(i))
})
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 把颜色值转换成rgb方式,设定多少秒改变完成,每次改变多少值,计算需要多少次
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> ,比如rba(x,y,z)到rgb(a,b,c),假设需要100次,那么每次设定
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> rgb((a-x)/100+x,(b-y)/100+y,(c-z)/100+z)</span>
<span style="color: rgba(0, 0, 255, 1)">var</span> count = Math.ceil(calibrationCount / (calibrationColorWheel.length - <span style="color: rgba(128, 0, 128, 1)">1</span>)); <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 渐变次数</span>
calibrationColors =<span style="color: rgba(0, 0, 0, 1)"> [];
</span><span style="color: rgba(0, 0, 255, 1)">for</span> (<span style="color: rgba(0, 0, 255, 1)">var</span> i = <span style="color: rgba(128, 0, 128, 1)">0</span>; i < colors.length - <span style="color: rgba(128, 0, 128, 1)">1</span>; i++<span style="color: rgba(0, 0, 0, 1)">) {
</span><span style="color: rgba(0, 0, 255, 1)">for</span> (<span style="color: rgba(0, 0, 255, 1)">var</span> j = <span style="color: rgba(128, 0, 128, 1)">1</span>; j <= count; j++<span style="color: rgba(0, 0, 0, 1)">) {
</span><span style="color: rgba(0, 0, 255, 1)">var</span> item = <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">rgb(</span><span style="color: rgba(128, 0, 0, 1)">'</span>
+ Math.round((colors[<span style="color: rgba(128, 0, 128, 1)">0</span>] - colors[<span style="color: rgba(128, 0, 128, 1)">0</span>]) / j + colors[<span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">])
</span>+ <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">,</span><span style="color: rgba(128, 0, 0, 1)">'</span>
+ Math.round((colors[<span style="color: rgba(128, 0, 128, 1)">1</span>] - colors[<span style="color: rgba(128, 0, 128, 1)">1</span>]) / j + colors[<span style="color: rgba(128, 0, 128, 1)">1</span><span style="color: rgba(0, 0, 0, 1)">])
</span>+ <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">,</span><span style="color: rgba(128, 0, 0, 1)">'</span>
+ Math.round((colors[<span style="color: rgba(128, 0, 128, 1)">2</span>] - colors[<span style="color: rgba(128, 0, 128, 1)">2</span>]) / j + colors[<span style="color: rgba(128, 0, 128, 1)">2</span><span style="color: rgba(0, 0, 0, 1)">])
</span>+ <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">)</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">;
calibrationColors.push(item)
}
}
}</span></pre>
</div>
<p>效果图:</p>
<p><img src="https://img2018.cnblogs.com/blog/1496396/201907/1496396-20190728131929227-1638003267.jpg"></p>
<h2>4.绘制指针</h2>
<p>这个主要是根据三角函数去计算相对圆心的偏移角度,按照当前值和刻度最大值的比例来计算偏移量,然后换算成对应的坐标。</p>
<p>主要代码:</p>
<div class="cnblogs_code">
<pre>pointer =<span style="color: rgba(0, 0, 0, 1)"> {
x: origin.x </span>+ (ringRadio - pointerRadio - ringBorderWidth) * Math.cos(startAngle - Math.PI * <span style="color: rgba(128, 0, 128, 1)">2</span> * calibrationPercent *<span style="color: rgba(0, 0, 0, 1)"> percent),
y: origin.y </span>- (ringRadio - pointerRadio - ringBorderWidth) * Math.sin(startAngle - Math.PI * <span style="color: rgba(128, 0, 128, 1)">2</span> * calibrationPercent *<span style="color: rgba(0, 0, 0, 1)"> percent),
r: pointerRadio,
color: percent </span>> <span style="color: rgba(128, 0, 128, 1)">0</span> ?<span style="color: rgba(0, 0, 0, 1)"> calibrationBrightColor : calibrationDarkColor,
show: </span><span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">,
}
</span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (pointerShow) {
g.beginPath();
g.fillStyle </span>=<span style="color: rgba(0, 0, 0, 1)"> pointer.color;
g.arc(pointer.x, pointer.y, pointer.r, </span><span style="color: rgba(128, 0, 128, 1)">0</span>, Math.PI * <span style="color: rgba(128, 0, 128, 1)">2</span><span style="color: rgba(0, 0, 0, 1)">);
g.closePath();
g.fill();
}</span></pre>
</div>
<p>效果图:</p>
<p><img src="https://img2018.cnblogs.com/blog/1496396/201907/1496396-20190728132240232-1504034869.jpg"></p>
<h2>5.绘制标尺</h2>
<p>计算标尺角度的算法同指针。</p>
<p>主要代码:</p>
<div class="cnblogs_code">
<pre>scaleLine =<span style="color: rgba(0, 0, 0, 1)"> {
startx: origin.x,
starty: origin.y,
endx: origin.x </span>+ (ringRadio + ringBorderWidth + 2 * calibrationHeight) * Math.cos(startAngle - Math.PI * 2 * calibrationPercent *<span style="color: rgba(0, 0, 0, 1)"> percent),
endy: origin.y </span>- (ringRadio + ringBorderWidth + 2 * calibrationHeight) * Math.sin(startAngle - Math.PI * 2 * calibrationPercent *<span style="color: rgba(0, 0, 0, 1)"> percent),
color: percent </span>> 0 ?<span style="color: rgba(0, 0, 0, 1)"> calibrationBrightColor : calibrationDarkColor,
show: scaleLineShow,
}
</span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (scaleLine) {
g.beginPath();
g.strokeStyle </span>= 'red'<span style="color: rgba(0, 0, 0, 1)">;
g.setLineDash([</span>1, 2<span style="color: rgba(0, 0, 0, 1)">]);
g.lineWidth </span>= 0.5 *<span style="color: rgba(0, 0, 0, 1)"> calibrationWidth;
g.moveTo(scaleLine.startx, scaleLine.starty);
g.lineTo(scaleLine.endx, scaleLine.endy);
g.closePath();
g.stroke();
}</span></pre>
</div>
<p>效果图:</p>
<p><img src="https://img2018.cnblogs.com/blog/1496396/201907/1496396-20190728132518236-468392742.jpg"></p>
<h2>6.绘制文本</h2>
<p>这里主要的就是确定文本所要绘制的位置,然后根据 <span style="font-family: "times new roman", times">ht.Default.getTextSize()</span> 来获取文本长度,方便设置文本居中。</p>
<p>主要代码:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (labelShow) {
</span><span style="color: rgba(0, 0, 255, 1)">var</span> text =<span style="color: rgba(0, 0, 0, 1)"> ht.Default.getTextSize(font, value);
g.fillStyle </span>=<span style="color: rgba(0, 0, 0, 1)"> labelColor;
g.font </span>=<span style="color: rgba(0, 0, 0, 1)"> font;
g.fillText(value.toFixed(</span>2<span style="color: rgba(0, 0, 0, 1)">), labelDot.x, labelDot.y);
}</span></pre>
</div>
<p>效果图:</p>
<p><img src="https://img2018.cnblogs.com/blog/1496396/201907/1496396-20190728132653065-899820612.jpg"></p>
<p>到这就完成了基本的旋钮组件,下面继续做一些细节上的优化。</p>
<p>例如加一些阴影效果,颜色渐变,配色调整等。</p>
<p>主要代码:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">var</span> backgroundRadial = g.createRadialGradient(x + 0.5 * width, y + 0.2 * height, 0, x + 0.5 * width, y + 0.2 * height, Math.sqrt(Math.pow(width / 2, 2) + Math.pow(height, 2<span style="color: rgba(0, 0, 0, 1)">)));
backgroundRadial.addColorStop(</span>0, 'rgba(220,220,220,1)'<span style="color: rgba(0, 0, 0, 1)">);
backgroundRadial.addColorStop(</span>1<span style="color: rgba(0, 0, 0, 1)">, backgroundColor);
g.fillStyle </span>=<span style="color: rgba(0, 0, 0, 1)"> backgroundRadial;
g.fillRect(x, y, width, height);
g.beginPath();
</span><span style="color: rgba(0, 0, 255, 1)">var</span> ringRadial = g.createRadialGradient(origin.x, origin.y - ringRadio / 2, 0, origin.x, origin.y - ringRadio / 2, 1.5 *<span style="color: rgba(0, 0, 0, 1)"> ringRadio);
ringRadial.addColorStop(</span>0, ht.Default.brighter(ringColor, 40<span style="color: rgba(0, 0, 0, 1)">));
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> ringRadial.addColorStop(0.25, ht.Default.brighter(ringColor, 40));</span>
ringRadial.addColorStop(1, ht.Default.darker(ringColor, 20<span style="color: rgba(0, 0, 0, 1)">));
</span><span style="color: rgba(0, 0, 255, 1)">var</span> borderRadial = g.createRadialGradient(origin.x, origin.y, ringRadio - ringBorderWidth / 2, origin.x, origin.y, ringRadio + ringBorderWidth / 2<span style="color: rgba(0, 0, 0, 1)">);
borderRadial.addColorStop(</span>0, ht.Default.brighter(ringBorderColor, 2<span style="color: rgba(0, 0, 0, 1)">));
borderRadial.addColorStop(</span>0.5, ht.Default.brighter(ringBorderColor, 4<span style="color: rgba(0, 0, 0, 1)">));
borderRadial.addColorStop(</span>1, ht.Default.darker(ringBorderColor, 4<span style="color: rgba(0, 0, 0, 1)">));
g.fillStyle </span>=<span style="color: rgba(0, 0, 0, 1)"> ringRadial;
g.lineWidth </span>=<span style="color: rgba(0, 0, 0, 1)"> ringBorderWidth;
g.strokeStyle </span>=<span style="color: rgba(0, 0, 0, 1)"> borderRadial;
g.arc(origin.x, origin.y, ringRadio, </span>0, 2 *<span style="color: rgba(0, 0, 0, 1)"> Math.PI);
g.closePath();
g.fill();
g.shadowBlur </span>= 20<span style="color: rgba(0, 0, 0, 1)">;
g.shadowColor </span>=<span style="color: rgba(0, 0, 0, 1)"> shadowColor;
g.shadowOffsetY </span>=<span style="color: rgba(0, 0, 0, 1)"> ringBorderWidth;
g.stroke();
g.shadowBlur </span>= 0<span style="color: rgba(0, 0, 0, 1)">;
g.shadowOffsetY </span>= 0;</pre>
</div>
<p>效果图:</p>
<p><img src="https://img2018.cnblogs.com/blog/1496396/201907/1496396-20190728132845698-835209225.jpg"></p>
<h2> 7.交互效果</h2>
<p>以上就是绘制好了一张静态图,最后就只要再加上一些交互效果就可以了。<br>这里我采用的是 <span style="font-family: "times new roman", times">HT for Web</span> 的矢量来实现。可参考 → 戳这</p>
<p>监听 <span style="font-family: "times new roman", times">onUp</span> 和<span style="font-family: "times new roman", times"> onDraw</span> 事件。<br><span style="font-family: "times new roman", times">onUp</span>:<br>当鼠标抬起时,获取当前旋钮显示的值,然后四舍五入,取其最近的刻度校准,使用 <span style="font-family: "times new roman", times">ht.Default.startAnim()</span> 添加动画效果。<br><span style="font-family: "times new roman", times">onDraw</span>:<br>根据当前鼠标停留的位置,以旋钮原点为参照点,根据三角函数来计算指针和起始刻度的夹角 <span style="font-family: "times new roman", times">A</span> ,计算 <span style="font-family: "times new roman", times">A</span> 占总刻度的百分比 <span style="font-family: "times new roman", times">p</span> ,然后设置当前值为 <span style="font-family: "times new roman", times">max * p</span> 。</p>
<p>最后使用 HT 实现:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">var</span> gv = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> ht.graph.GraphView();
dm </span>=<span style="color: rgba(0, 0, 0, 1)"> gv.dm();
dm.a(</span>'pannable', <span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">);
dm.a(</span>'zoomable', <span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">);
dm.a(</span>'rectSelectable', <span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">);
ht.Default.setCompType(</span>'knob',func); <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">注册组件</span>
ht.Default.setImage('iconKnob', data); <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">注册图片</span>
<span style="color: rgba(0, 0, 255, 1)">var</span> node = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> ht.Node();
node.setImage(</span>'iconKnob'<span style="color: rgba(0, 0, 0, 1)">);
node.s(</span>'2d.movable', <span style="color: rgba(0, 0, 255, 1)">false</span><span style="color: rgba(0, 0, 0, 1)">);
dm.add(node);
gv.fitContent();
gv.addToDOM();
window.addEventListener(
</span>'resize'<span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">(e) {
gv.invalidate();
gv.fitContent();
},
</span><span style="color: rgba(0, 0, 255, 1)">false</span><span style="color: rgba(0, 0, 0, 1)">
);</span></pre>
</div><br><br>
来源:https://www.cnblogs.com/htdaydayup/p/11258689.html
頁:
[1]