autojs绘画实现六边形示例详解

目录
  • 界面基础代码
    • 创建Hexagon类
    • 界面布局
    • 画板事件
  • 计算并绘制六边形中心点
    • 计算六边形六个点的坐标
    • 计算六边形的path
  • 绘制六边形
  • 绘制一排六边形
    • 确定边界条件
  • 考虑两个相邻的六边形连接处
  • 限制一排六边形最后一个的边界
  • 画第二排六边形
  • 绘制多排六边形
  • 先画一组
  • 一组一组的计算坐标
    • 环境

界面基础代码

"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 &lt; 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) =&gt; {
  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文档, 最后才是群里问问 ---

部分内容来自网络 本教程仅用于学习, 禁止用于其他用途

以上就是autojs画六边形实现示例详解的详细内容,更多关于autojs绘画实现六边形的资料请关注我们其它相关文章!

(0)

相关推荐

  • autojs模仿QQ长按弹窗菜单实现示例详解二

    目录 引言 弹窗菜单 箭头 如何确认箭头方向? 调整popwindow的位置 调用方法如下 绘制箭头 修改颜色和圆角 给弹框菜单添加点击事件 弹框菜单点击事件引用弹框实例 环境 引言 上一节讲了列表和长按事件 autojs模仿QQ长按弹窗菜单 弹窗菜单 由粗到细, 自顶向下的写代码 我们现在要修改的文件是showMenuWindow.js function showMenuWindow(view) { let popMenuWindow = ui.inflateXml( view.getCont

  • autojs模仿QQ长按弹窗菜单实现示例

    目录 分析弹框菜单 需求分析 代码分析 RecyclerView基础代码 长按事件 环境 分析弹框菜单 圆角 列表, 类似grid 箭头位于文字中间上(下)方 需求分析 如果要写一个这样的教程, 我们需要做什么 写一个列表, 用来触发长按选项 写一个弹窗菜单 代码分析 列表怎么写, 先来一个最简单的布局代码 "nodejs ui"; require("rhino").install(); const ui = require("ui"); cla

  • autojs绘画实现六边形示例详解

    目录 界面基础代码 创建Hexagon类 界面布局 画板事件 计算并绘制六边形中心点 计算六边形六个点的坐标 计算六边形的path 绘制六边形 绘制一排六边形 确定边界条件 考虑两个相邻的六边形连接处 限制一排六边形最后一个的边界 画第二排六边形 绘制多排六边形 先画一组 一组一组的计算坐标 环境 界面基础代码 "nodejs ui"; require("rhino").install(); const ui = require("ui"); c

  • Flutter CustomPaint自定义绘画示例详解

    目录 正文 CustomPaint 介绍 绘制点 PointMode3种模式 绘制线 和路径 绘制五子棋 总结 正文 CustomPaint是Flutter中用于自由绘制的一个widget,它与android原生的绘制规则基本一致,以当前Canves(画布)的左上角为原点进行绘制.在有些场景中,我们会需要绘制一些高度定制化的组件,比如 UI 设计师给我们出了个难题 —— 弄一个奇形怪状的边框.这个时候我们就不能直接使用 Flutter 自带的那些组件了,而是需要手动绘制组件,那就会需要用到 Cu

  • Python中八大图像特效算法的示例详解

    目录 0写在前面 1毛玻璃特效 2浮雕特效 3油画特效 4马赛克特效 5素描特效 6怀旧特效 7流年特效 8卡通特效 0 写在前面 图像特效处理是基于图像像素数据特征,将原图像进行一定步骤的计算——例如像素作差.灰度变换.颜色通道融合等,从而达到期望的效果.图像特效处理是日常生活中应用非常广泛的一种计算机视觉应用,出现在各种美图软件中,这些精美滤镜背后的数学原理都是相通的,本文主要介绍八大基本图像特效算法,在这些算法基础上可以进行二次开发,生成更高级的滤镜. 本文采用面向对象设计,定义了一个图像

  • Android开发Kotlin实现圆弧计步器示例详解

    目录 效果图 定义控件的样式 自定义StepView 绘制文本坐标 Android获取中线到基线距离 效果图 定义控件的样式 看完效果后,我们先定义控件的样式 <!-- 自定义View的名字 StepView --> <!-- name 属性名称 format 格式 string 文字 color 颜色 dimension 字体大小 integer 数字 reference 资源或者颜色 --> <declare-styleable name="StepView&q

  • AngularJS的Filter的示例详解

    贴上几个有关Filter使用的几个示例. 1. 首先创建一个表格 <body ng-app="app"> <div class="divAll" ng-controller="tableFilter"> <input type="text" placeholder="输入你要搜索的内容" ng-model="key"> <br><br

  • bat批处理 if 命令示例详解

    if 命令示例详解 if,正如它E文中的意思,就是"如果"的意思,用来进行条件判断.翻译过来的意思就是:如果符合某一条件,便执行后面的命令. 主要用来判断,1.两个"字符串"是否相等:2.两个数值是大于.小于.等于,然后执行相应的命令. 当然还有特殊用法,如结合errorlevel:if errorlevel 1 echo error 或者结合defined(定义的意思):if defined test (echo It is defined) else echo 

  • Docker-Compose的使用示例详解

    Docker Compose是一个用来定义和运行复杂应用的Docker工具.使用Compose,你可以在一个文件中定义一个多容器应用,然后使用一条命令来启动你的应用,完成一切准备工作. - github.com/docker/compose docker-compose是用来在Docker中定义和运行复杂应用的工具,比如在一个yum文件里定义多个容器,只用一行命令就可以让一切就绪并运行. 使用docker compose我们可以在Run的层面解决很多实际问题,如:通过创建compose(基于YU

  • jQuery.Validate表单验证插件的使用示例详解

    jQuery Validate 插件为表单提供了强大的验证功能,让客户端表单验证变得更简单,同时提供了大量的定制选项,满足应用程序各种需求. 请在这里查看示例 validate示例 示例包含 验证错误时,显示红色错误提示 自定义验证规则 引入中文错误提示 重置表单需要执行2句话 源码示例 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <

  • JavaScript中自带的 reduce()方法使用示例详解

    1.方法说明 , Array的reduce()把一个函数作用在这个Array的[x1, x2, x3...]上,这个函数必须接收两个参数,reduce()把结果继续和序列的下一个元素做累积计算,其效果就是: [x1, x2, x3, x4].reduce(f) = f(f(f(x1, x2), x3), x4) 2. 使用示例 'use strict'; function string2int(s){ if(!s){ alert('the params empty'); return; } if

随机推荐