牙叔教程 简单易懂
界面基础代码
"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文档, 最后才是群里问问 --- 牙叔教程
声明
部分内容来自网络 本教程仅用于学习, 禁止用于其他用途