牙叔教程 简单易懂
界面基础代码
"nodejs ui"; require("rhino").install(); const ui = require("ui"); class MainActivity extends ui.Activity { constructor() { super(); } get layoutXmlFile() { return "layout.xml"; } onContentViewSet() {} } ui.setMainActivity(MainActivity);
创建Hexagon类
class Hexagon {}
至于需要的属性, 有需求的时候再写
界面布局
<column> <canvas id="canvas" w="*" h="*"> </canvas> </column>
画板事件
onContentViewSet(view) { const canvasView = view.binding.canvas; canvasView.on("draw", (canvas) => { canvas.drawColor(canvasBgColor); }); }
计算并绘制六边形中心点
let canvasWidth = canvasView.getWidth(); let canvasHeight = canvasView.getHeight(); let centerX = canvasWidth / 2; let centerY = canvasHeight / 2; canvasView.on("draw", (canvas) => { canvas.drawColor(canvasBgColor); canvas.drawPoint(centerX, centerY, paint); });
计算六边形六个点的坐标
这个方法应该属于六边形这个类
getSixPoints() { let points = []; let angle = 0; for (let i = 0; i < 6; i++) { let x = this.centerX + this.sideLength * Math.cos(angle); let y = this.centerY - this.sideLength * Math.sin(angle); points.push({ x, y }); angle += Math.PI / 3; } return points; }
计算六边形的path
这个也属于六边形的方法
getPath() { const path = new Path(); let points = this.getSixPoints(); path.moveTo(points[0].x, points[0].y); for (let i = 1; i < points.length; i++) { path.lineTo(points[i].x, points[i].y); } path.close(); return path; }
绘制六边形
let hexagon = new Hexagon(centerX, centerY, config.sideLength); let hexagonPath = hexagon.getPath(); canvasView.on("draw", (canvas) => { canvas.drawColor(canvasBgColor); canvas.drawPoint(centerX, centerY, paint); canvas.drawPath(hexagonPath, paint); });
绘制一排六边形
要绘制一排, 那么六边形左右两边需要是数直的, 把 getSixPoints 方法里的 sin 和 cos 对调一下即可
let x = this.centerX + this.sideLength * Math.sin(angle); let y = this.centerY - this.sideLength * Math.cos(angle);
确定边界条件
所有六边形都要在画板内, 我们画左上角第一个六边形;
计算中心点要考虑的条件
- 画笔的宽度
- 六边形边长
let angle = Math.PI / 3; let firstHexagonCenterX = config.sideLength * Math.sin(angle) + config.paintConfig.width; let firstHexagonCenterY = config.sideLength + config.paintConfig.width;
考虑两个相邻的六边形连接处
两个挨着的竖边, 应该只需要画一条, 那么来计算第二个六边形的中心位置, 以第一个六边形为参照物
let secondHexagonCenterX = firstHexagonCenterX + config.sideLength * Math.sin(angle) * 2; let secondHexagonCenterY = firstHexagonCenterY;
绘制出的两个六边形
改了一下宽度, 方便观察
限制一排六边形最后一个的边界
最后一个六边形的最右侧的边, 不能超过画板
let hexagonPaths = []; let count = 1; while (1) { let nextHexagonCenterX = firstHexagonCenterX + config.sideLength * Math.sin(angle) * 2 * count; if (nextHexagonCenterX + config.sideLength * Math.sin(angle) + config.paintConfig.width > canvasWidth) { break; } let nextHexagonCenterY = firstHexagonCenterY; let nextHexagon = new Hexagon(nextHexagonCenterX, nextHexagonCenterY, config.sideLength); let nextHexagonPath = nextHexagon.getPath(); hexagonPaths.push(nextHexagonPath); count++; }
for (let i = 0; i < hexagonPaths.length; i++) { canvas.drawPath(hexagonPaths[i], paint); }
画第二排六边形
计算第二排第一个六边形的中心点
let nextRowFirstHexagonCenterX = firstHexagonCenterX + config.sideLength * Math.sin(angle); let nextRowFirstHexagonCenterY = firstHexagonCenterY + config.sideLength * Math.cos(angle) + config.sideLength; let nextRowFirstHexagon = new Hexagon(nextRowFirstHexagonCenterX, nextRowFirstHexagonCenterY, config.sideLength); let nextRowFirstHexagonPath = nextRowFirstHexagon.getPath();
与第一排同理, 画第二排
绘制多排六边形
很明显, 我们要使用循环, 横着要循环, 竖着也要循环, 那么这个循环怎么写呢?
我们一组一组的计算六边形中心点, 一组有两排六边形:
- 第一排5个
- 第二排4个
下一组, 往下移动 3 个边长,
因为第一组, 我们已经检查过画板右侧,
所以, 接下来的计算, 只需要考虑画板底部, 不需要判断画板右侧了;
我们改变的只有纵坐标
先画一组
let firstRow = []; let secondRow = []; let firstGroup = [firstRow, secondRow]; let firstRowCount = 0; while (1) { let centerX = firstHexagonCenterX + firstRowCount * config.sideLength * 2 * Math.sin(angle); if (centerX > canvasWidth - config.sideLength * Math.sin(angle) - config.paintConfig.width) { break; } let centerY = firstHexagonCenterY; firstRow.push(new Hexagon(centerX, centerY, config.sideLength)); firstRowCount++; } /* -------------------------------------------------------------------------- */ let secondRowCount = 0; while (1) { let centerX = firstHexagonCenterX + secondRowCount * config.sideLength * 2 * Math.sin(angle) + config.sideLength * Math.sin(angle); if (centerX > canvasWidth - config.sideLength * Math.sin(angle) - config.paintConfig.width) { break; } let centerY = firstHexagonCenterY + config.sideLength + config.sideLength * Math.cos(angle); secondRow.push(new Hexagon(centerX, centerY, config.sideLength)); secondRowCount++; } hexagons = firstGroup.flat(); let hexagonPaths = hexagons.map((hexagon) => hexagon.getPath()); /* -------------------------------------------------------------------------- */ canvasView.on("draw", (canvas) => { canvas.drawColor(canvasBgColor); for (let i = 0; i < hexagonPaths.length; i++) { canvas.drawPath(hexagonPaths[i], paint); } });
这是一个二维数组, 我们用flat抹平成一维数组
一组一组的计算坐标
y坐标依次增长3个边长即可
先计算第一排, 再计算第二排
let row = 1; while (1) { let nextGroupFirstRow = []; let nextGroupSecondRow = []; let nextGroup = [nextGroupFirstRow, nextGroupSecondRow]; let firstGroupFirstRow = firstGroup[0]; let firstGroupFirstHexagon = firstGroupFirstRow[0]; if (firstGroupFirstHexagon.centerY + config.sideLength * 3 * row > canvasHeight) { break; } nextGroupFirstRow = firstGroupFirstRow.map((hexagon) => { let centerX = hexagon.centerX; let centerY = hexagon.centerY + config.sideLength * 3 * row; nextGroupFirstRow.push(new Hexagon(centerX, centerY, config.sideLength)); }); let firstGroupSecondRow = firstGroup[1]; let firstGroupSecondHexagon = firstGroupSecondRow[0]; if (firstGroupSecondHexagon.centerY + config.sideLength * 3 * row > canvasHeight) { break; } nextGroupSecondRow = firstGroupSecondRow.map((hexagon) => { let centerX = hexagon.centerX; let centerY = hexagon.centerY + config.sideLength * 3 * row; nextGroupSecondRow.push(new Hexagon(centerX, centerY, config.sideLength)); }); groups.push(nextGroup); row++; } hexagons = groups.flat(2); let hexagonPaths = hexagons.map((hexagon) => hexagon.getPath());
环境
设备: 小米11pro
Android版本: 12
Autojs版本: 9.3.11
名人名言
思路是最重要的, 其他的百度, bing, stackoverflow, github, 安卓文档, autojs文档, 最后才是群里问问 --- 牙叔教程
声明
部分内容来自网络 本教程仅用于学习, 禁止用于其他用途