苏州电商网站建设手机发布 wordpress文章

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

苏州电商网站建设,手机发布 wordpress文章,国内信息图制作网站,网站排版类型本节笔者带领读者实现一个饼状图 PieChart 组件#xff0c;该组件是根据笔者之前封装的 MiniCanvas 实现的#xff0c; PieChart 的最终演示效果如下图所示#xff1a;
饼状图实现的拆分 根据上图的样式效果#xff0c;实现一个饼状图#xff0c;实质就是绘制一个个的实…本节笔者带领读者实现一个饼状图 PieChart 组件该组件是根据笔者之前封装的 MiniCanvas 实现的 PieChart 的最终演示效果如下图所示
饼状图实现的拆分 根据上图的样式效果实现一个饼状图实质就是绘制一个个的实心圆弧加上圆弧对应颜色就搞定了圆弧的大小是根据饼状的数据分布计算出来的对应的颜色自己指定就可以了其次手指点击到饼状图需要找到对应的饼状块并突出显示找到饼状块先计算手指点击坐标和圆弧中心的夹角根据夹角和每个圆弧的大小找到对应的圆弧找到圆弧后计算圆弧的突出偏移量并重置所有饼状块的圆弧起始值就可以了。 计算夹角 计算夹角就是计算手指点击饼状图上的坐标 (x, y) 和饼状图的圆心坐标 (centerX, centerY) 之间的顺时针角度计算方法如下所示 private getTouchedAngle(centerX: number, centerY, x: number, y: number) {var deltaX x - centerX;var deltaY centerY - y;var t deltaY / Math.sqrt(deltaX * deltaX deltaY * deltaY);var angle 0;if (deltaX 0) {if (deltaY 0) {angle Math.asin(t);} else {angle Math.PI * 2 Math.asin(t);}} else if (deltaY 0) {angle Math.PI - Math.asin(t);} else {angle Math.PI - Math.asin(t);}return 360 - (angle * 180 / Math.PI) % 360; }找圆弧块 计算出手指点击位置和圆心的夹角后遍历每一个饼状块做比较就可以了代码如下所示 private getTouchedPieItem(angle: number): PieItem {for(var i 0; i this.pieItems.length; i) {var item this.pieItems[i];if(item.getStopAngle() 360) {if(angle item.getStartAngle() angle item.getStopAngle()) {return item;}} else {if(angle item.getStartAngle() angle 360 || (angle 0 angle item.getStopAngle() - 360)) {return item;}}}return null; }计算偏移量 找到圆弧块后根据圆弧块的圆弧大小计算出该圆弧突出后的偏移量代码如下所示 private calculateRoteAngle(item: PieItem): number {var result item.getStartAngle() item.getAngle() / 2 this.getDirectionAngle();if (result 360) {result - 360;}if (result 180) {result -result;} else {result 360 - result;}return result; }重置偏移量 有了目标圆弧块的偏移角度后重置每一个圆弧块的起始偏移量就可以了代码如下所示 private resetStartAngle(angle: number) {this.pieItems.forEach((item) {item.setSelected(false);item.setStartAngle(item.getStartAngle() angle);}); }重新绘制圆弧 绘制圆弧使用 MiniCanvas 提供的 drawArc() 方法即可代码如下所示 drawPieItem() {this.pieItems.forEach((item) {this.paint.setColor(item.color);var x this.calculateCenterX(item.isSelected());var y this.calculateCenterY(item.isSelected());this.canvas.drawArc(x, y, this.radius, item.getStartAngle(), item.getStopAngle(), this.paint);}) }饼状图的实现 拆分完饼状图的步骤后实现起来就方便多了 PieChart 的完整代码如下所示 import { MiniCanvas, Paint, ICanvas } from ./icanvasEntry Component struct PieChart {private delegate: PieChartDelegate;build() {Column() {MiniCanvas({attribute: {width: this.delegate.calculateWidth(),height: this.delegate.calculateHeight(),clickListener: (event) {// 根据点击绘制突出的饼状块this.delegate.onClicked(event.x, event.y);}},onDraw: (canvas) {// 开始绘制this.delegate.setCanvas(canvas);this.delegate.drawPieItem();}})}.padding(10).size({width: 100%, height: 100%})}aboutToAppear() {// mock测试数据var pieItems PieItem.mock();// 初始化delegatethis.delegate new PieChartDelegate(pieItems, RotateDirection.BOTTOM);} }// 定义饼状块的属性包括角度起始角度占比颜色是否选中突出 export class PieItem {private startAngle: number 0;private rate: number 0;private angle: number 0;private selected: boolean false;constructor(public count: number, public color: string) {}setSelected(selected: boolean) {this.selected selected;return this;}isSelected() {return this.selected;}setStartAngle(startAngle: number) {this.startAngle startAngle 360 ? startAngle - 360 : startAngle 0 ? 360 startAngle : startAngle;return this;}getStartAngle() {return this.startAngle;}getStopAngle() {return this.startAngle this.angle;}setRate(rate: number) {this.rate rate;return this;}getRate() {return this.rate;}setAngle(angle: number) {this.angle angle;return this;}getAngle() {return this.angle;}// mock一份测试数据static mock(): ArrayPieItem {var pieItems new ArrayPieItem();pieItems.push(new PieItem(21, #6A5ACD))pieItems.push(new PieItem(18, #20B2AA))pieItems.push(new PieItem(29, #FFFF00))pieItems.push(new PieItem(12, #00BBFF))pieItems.push(new PieItem(20, #DD5C5C))pieItems.push(new PieItem(13, #8B668B))return pieItems;} }// 饼状块的突出方向 export enum RotateDirection {LEFT,TOP,RIGHT,BOTTOM }// 饼状图绘制的具体实现类 class PieChartDelegate {private paint: Paint;private canvas: ICanvas;constructor(private pieItems: ArrayPieItem, private direction: RotateDirection RotateDirection.BOTTOM, private offset: number 10, private radius: number 80) {this.calculateItemAngle();}setPitItems(pieItems: ArrayPieItem) {this.pieItems pieItems;}setCanvas(canvas: ICanvas) {this.canvas canvas;this.paint new Paint();}onClicked(x: number, y: number) {if(this.canvas) {var touchedAngle this.getTouchedAngle(this.radius, this.radius, x, y);var touchedItem this.getTouchedPieItem(touchedAngle);if(touchedItem) {var rotateAngle this.calculateRoteAngle(touchedItem);this.resetStartAngle(rotateAngle);touchedItem.setSelected(true)this.clearCanvas();this.drawPieItem();}} else {console.warn(canvas invalid!!!)}}clearCanvas() {this.canvas.clear();}drawPieItem() {this.pieItems.forEach((item) {this.paint.setColor(item.color);var x this.calculateCenterX(item.isSelected());var y this.calculateCenterY(item.isSelected());this.canvas.drawArc(x, y, this.radius, item.getStartAngle(), item.getStopAngle(), this.paint);})}calculateWidth(): number {if (this.direction RotateDirection.LEFT || this.direction RotateDirection.RIGHT) {return this.radius * 2 this.offset;} else {return this.radius * 2;}}calculateHeight(): number {if (this.direction RotateDirection.TOP || this.direction RotateDirection.BOTTOM) {return this.radius * 2 this.offset;} else {return this.radius * 2;}}private calculateCenterX(hint: boolean): number {if(this.direction RotateDirection.LEFT) {return hint ? this.radius : this.radius this.offset;} else if(this.direction RotateDirection.TOP) {return this.radius;} else if(this.direction RotateDirection.RIGHT) {return hint ? this.radius this.offset : this.radius;} else {return this.radius;}}private calculateCenterY(hint: boolean): number {if(this.direction RotateDirection.LEFT) {return this.radius;} else if(this.direction RotateDirection.TOP) {return hint ? this.radius : this.radius this.offset;} else if(this.direction RotateDirection.RIGHT) {return this.radius;} else {return hint ? this.radius this.offset : this.radius;}}private resetStartAngle(angle: number) {this.pieItems.forEach((item) {item.setSelected(false);item.setStartAngle(item.getStartAngle() angle);});}private calculateRoteAngle(item: PieItem): number {var result item.getStartAngle() item.getAngle() / 2 this.getDirectionAngle();if (result 360) {result - 360;}if (result 180) {result -result;} else {result 360 - result;}return result;}private calculateItemAngle() {var total 0;this.pieItems.forEach((item) {total item.count;})for(var i 0; i this.pieItems.length; i) {var data this.pieItems[i];data.setRate(data.count / total);data.setAngle(data.getRate() * 360);if (i 0) {data.setStartAngle(0);} else {var preData this.pieItems[i - 1];data.setStartAngle(preData.getStopAngle());}}}private getDirectionAngle(): number {var result 270;if (this.direction RotateDirection.RIGHT) {result 0;}if (this.direction RotateDirection.BOTTOM) {result 270;}if (this.direction RotateDirection.LEFT) {result 180;}if (this.direction RotateDirection.TOP) {result 90;}return result;}private getTouchedAngle(centerX: number, centerY, x: number, y: number) {var deltaX x - centerX;var deltaY centerY - y;var t deltaY / Math.sqrt(deltaX * deltaX deltaY * deltaY);var angle 0;if (deltaX 0) {if (deltaY 0) {angle Math.asin(t);} else {angle Math.PI * 2 Math.asin(t);}} else if (deltaY 0) {angle Math.PI - Math.asin(t);} else {angle Math.PI - Math.asin(t);}return 360 - (angle * 180 / Math.PI) % 360;}private getTouchedPieItem(angle: number): PieItem {for(var i 0; i this.pieItems.length; i) {var item this.pieItems[i];if(item.getStopAngle() 360) {if(angle item.getStartAngle() angle item.getStopAngle()) {return item;}} else {if(angle item.getStartAngle() angle 360 || (angle 0 angle item.getStopAngle() - 360)) {return item;}}}return null;} }以上就是笔者介绍的实现一个饼状图的思路和实现读者可以阅读源码目前 PieChart 在选中饼状块并突出时没有动画特效而是直接旋转过来了后续笔者会把旋转的动效加上。