Commit 15a7620e authored by hucy's avatar hucy

fix:不重要的提交

parent b0925c4c
...@@ -12,6 +12,7 @@ export * from './get-type'; ...@@ -12,6 +12,7 @@ export * from './get-type';
export * from './is'; export * from './is';
export * from './get-angle'; export * from './get-angle';
export * from './getBoundingBox'; export * from './getBoundingBox';
export * from './scale-polygon';
export { export {
cloneDeep, cloneDeep,
orderBy, orderBy,
......
interface Point {
x: number;
y: number;
[proppName: string]: any;
}
/**
* 缩放多边形坐标
* https://blog.csdn.net/sun_and_breeze/article/details/107517088
* @decoration 需配合顺时针判断方法一起使用
* @param {Point[]} points 点坐标数组 [{x:0,y:0}...]
* @param {number} extra 外延大小。为正: 向外扩; 为负: 向内缩
* @return {Point[]} 扩展或缩小后的多边形点坐标数组
*/
export function scalePolygon(points: Point[], extra: number) {
if (!Array.isArray(points) || points.length < 3) {
console.error('多边形坐标集合不能少于3个');
return;
}
const ps = points;
// 通过顺时针判断取正值还是负值
const extra0 = isClockwise(ps) ? -extra : extra;
const norm = (x: number, y: number) => Math.sqrt(x * x + y * y);
const len = ps.length;
const polygon = [];
for (let i = 0; i < len; i++) {
const point = ps[i];
const point1 = ps[i === 0 ? len - 1 : i - 1];
const point2 = ps[i === len - 1 ? 0 : i + 1];
// 向量PP1
const vectorX1 = point1.x - point.x; // 向量PP1 横坐标
const vectorY1 = point1.y - point.y; // 向量PP1 纵坐标
const n1 = norm(vectorX1, vectorY1); // 向量的平方根 为了对向量PP1做单位化
let vectorUnitX1 = vectorX1 / n1; // 向量单位化 横坐标
let vectorUnitY1 = vectorY1 / n1; // 向量单位化 纵坐标
// 向量PP2
const vectorX2 = point2.x - point.x; // 向量PP2 横坐标
const vectorY2 = point2.y - point.y; // 向量PP2 纵坐标
const n2 = norm(vectorX2, vectorY2); // 向量的平方根 为了对向量PP1做单位化
let vectorUnitX2 = vectorX2 / n2; // 向量单位化 横坐标
let vectorUnitY2 = vectorY2 / n2; // 向量单位化 纵坐标
// PQ距离
const vectorLen =
-extra0 /
Math.sqrt(
(1 - (vectorUnitX1 * vectorUnitX2 + vectorUnitY1 * vectorUnitY2)) / 2
);
// 根据向量的叉乘积来判断角是凹角还是凸角
if (vectorX1 * vectorY2 + -1 * vectorY1 * vectorX2 < 0) {
vectorUnitX2 *= -1;
vectorUnitY2 *= -1;
vectorUnitX1 *= -1;
vectorUnitY1 *= -1;
}
// PQ的方向
const vectorX = vectorUnitX1 + vectorUnitX2;
const vectorY = vectorUnitY1 + vectorUnitY2;
const n = vectorLen / norm(vectorX, vectorY);
const vectorUnitX = vectorX * n;
const vectorUnitY = vectorY * n;
const polygonX = vectorUnitX + point.x;
const polygonY = vectorUnitY + point.y;
polygon[i] = { x: polygonX, y: polygonY };
}
return polygon;
}
/**
* 判断坐标数组是否顺时针(默认为false)
* @param {Point[]} points 点坐标数组 [{x:0,y:0}...]
* @returns {boolean} 是否顺时针
*/
export function isClockwise(points: Point[]) {
// 三个点可以判断矢量是顺时针旋转还是逆时针旋转的,但由于可能存在凹边,所以并不是任意三点都可以正确反映多边形的走向
// 因此需要取多边形中绝对是凸边的点来判断,
// 多边形中的极值点(x最大或x最小或y最大或y最小)它与相邻两点构成的边必然是凸边,因此我们先取出多边形中的极值点,再由极值点和其前后两点去判断矢量的走向,从而判断出多边形的走向。
if (!Array.isArray(points) || points.length < 3) {
console.error('多边形坐标集合不能少于3个');
return false;
}
let coords = JSON.parse(JSON.stringify(points));
if (coords[0] === coords[coords.length - 1]) {
coords = coords.slice(0, coords.length - 1);
}
coords = coords.reverse();
let maxXIndex = 0;
let maxX = parseFloat(coords[maxXIndex].x);
let c1;
let c2;
let c3;
for (let i = 0; i < coords.length; i++) {
if (parseFloat(coords[i].x) > maxX) {
maxX = parseFloat(coords[i].x);
maxXIndex = i;
}
}
if (maxXIndex === 0) {
c1 = coords[coords.length - 1];
c2 = coords[maxXIndex];
c3 = coords[maxXIndex + 1];
} else if (maxXIndex === coords.length - 1) {
c1 = coords[maxXIndex - 1];
c2 = coords[maxXIndex];
c3 = coords[0];
} else {
c1 = coords[maxXIndex - 1];
c2 = coords[maxXIndex];
c3 = coords[maxXIndex + 1];
}
const x1 = parseFloat(c1.x);
const y1 = parseFloat(c1.y);
const x2 = parseFloat(c2.x);
const y2 = parseFloat(c2.y);
const x3 = parseFloat(c3.x);
const y3 = parseFloat(c3.y);
const s = (x1 - x3) * (y2 - y3) - (x2 - x3) * (y1 - y3);
return s < 0;
}
...@@ -132,10 +132,25 @@ export const MenuList = [ ...@@ -132,10 +132,25 @@ export const MenuList = [
{ {
title: 'Vue Konva', title: 'Vue Konva',
caption: '前端Canvas库-Konva', caption: '前端Canvas库-Konva',
icon: '',
active: false,
children: [
{
title: 'Konva',
caption: '',
icon: require('./menuListIcons/amis.svg'), icon: require('./menuListIcons/amis.svg'),
link: '/vue-konva', link: '/vue-konva',
active: false, active: false,
}, },
{
title: 'Line-多边形',
caption: '',
icon: require('./menuListIcons/amis.svg'),
link: '/vue-konva-line',
active: false,
},
],
},
{ {
title: '向量', title: '向量',
caption: 'JavaScript 线性代数:向量', caption: 'JavaScript 线性代数:向量',
......
...@@ -29,7 +29,7 @@ export const poems = [ ...@@ -29,7 +29,7 @@ export const poems = [
}, },
{ {
key: '3', key: '3',
author: '唐珙', author: '唐珙(gǒng)',
content: ['醉后不知天在水,满船清梦压星河'], content: ['醉后不知天在水,满船清梦压星河'],
style: { style: {
color: '#4AA5DA', color: '#4AA5DA',
...@@ -178,7 +178,7 @@ export const poems = [ ...@@ -178,7 +178,7 @@ export const poems = [
{ {
key: '18', key: '18',
author: '龚自珍', author: '龚自珍',
content: ['万一禅关砉然破,美人如玉剑如虹'], content: ['万一禅关砉(huā)然破,美人如玉剑如虹'],
style: { style: {
backgroundImage: backgroundImage:
'linear-gradient(25deg, #794a70, #8c6e90, #9e92b1, #aeb7d3)', 'linear-gradient(25deg, #794a70, #8c6e90, #9e92b1, #aeb7d3)',
...@@ -478,8 +478,8 @@ export const poems = [ ...@@ -478,8 +478,8 @@ export const poems = [
}, },
{ {
key: '46', key: '46',
author: '吴庆坻', author: '吴庆坻(dǐ)',
content: ['须知少日拏云志,曾许人间第一流'], content: ['须知少日拏(ná)云志,曾许人间第一流'],
style: { style: {
backgroundColor: '#F5F0E9', backgroundColor: '#F5F0E9',
color: '#57A5D1', color: '#57A5D1',
...@@ -509,7 +509,7 @@ export const poems = [ ...@@ -509,7 +509,7 @@ export const poems = [
}, },
{ {
key: '49', key: '49',
author: '李鼐', author: '李鼐(nài)',
content: ['从今把定春风笑,且作人间长寿仙'], content: ['从今把定春风笑,且作人间长寿仙'],
style: { style: {
backgroundImage: backgroundImage:
...@@ -630,7 +630,7 @@ export const poems = [ ...@@ -630,7 +630,7 @@ export const poems = [
}, },
{ {
key: '60', key: '60',
author: '舒亶', author: '舒亶(dǎn)',
content: ['浮生只合尊前老,雪满长安道'], content: ['浮生只合尊前老,雪满长安道'],
style: { style: {
backgroundImage: backgroundImage:
...@@ -659,7 +659,7 @@ export const poems = [ ...@@ -659,7 +659,7 @@ export const poems = [
}, },
{ {
key: '63', key: '63',
author: '钱珝', author: '钱珝(xǔ)',
content: ['莫愁千里路,自有到风来'], content: ['莫愁千里路,自有到风来'],
style: { style: {
backgroundColor: '#62676C', backgroundColor: '#62676C',
...@@ -770,7 +770,7 @@ export const poems = [ ...@@ -770,7 +770,7 @@ export const poems = [
}, },
{ {
key: '75', key: '75',
author: '姚鼐', author: '姚鼐(nài)',
content: ['苍山负雪,明烛天南'], content: ['苍山负雪,明烛天南'],
style: { style: {
backgroundImage: 'linear-gradient(to right, #d7d2cc 0%, #304352 100%)', backgroundImage: 'linear-gradient(to right, #d7d2cc 0%, #304352 100%)',
...@@ -829,7 +829,7 @@ export const poems = [ ...@@ -829,7 +829,7 @@ export const poems = [
author: '林清和', author: '林清和',
content: [ content: [
'你当然不是什么惊世骇俗之物,', '你当然不是什么惊世骇俗之物,',
'你只是凛冬中我愿“拥毳衣炉火”去看的白雪', '你只是凛冬中我愿“拥毳(cuì)衣炉火”去看的白雪',
], ],
style: { style: {
backgroundImage: 'linear-gradient(-20deg, #616161 0%, #9bc5c3 100%)', backgroundImage: 'linear-gradient(-20deg, #616161 0%, #9bc5c3 100%)',
...@@ -1069,7 +1069,7 @@ export const poems = [ ...@@ -1069,7 +1069,7 @@ export const poems = [
{ {
key: '106', key: '106',
author: '苏轼', author: '苏轼',
content: ['粗缯大布裹生涯,腹有诗书气自华'], content: ['粗缯(zēng)大布裹生涯,腹有诗书气自华'],
style: { style: {
backgroundImage: backgroundImage:
'linear-gradient(25deg, #1d6c99, #6d95b6, #aac1d4, #e7eff2)', 'linear-gradient(25deg, #1d6c99, #6d95b6, #aac1d4, #e7eff2)',
...@@ -1137,7 +1137,7 @@ export const poems = [ ...@@ -1137,7 +1137,7 @@ export const poems = [
{ {
key: '113', key: '113',
author: '袁枚', author: '袁枚',
content: ['学如弓弩,才如箭镞'], content: ['学如弓弩,才如箭镞(zú)'],
style: { style: {
backgroundImage: backgroundImage:
'linear-gradient(25deg, #624365, #846e8d, #a79cb6, #cbcce2)', 'linear-gradient(25deg, #624365, #846e8d, #a79cb6, #cbcce2)',
...@@ -1177,7 +1177,7 @@ export const poems = [ ...@@ -1177,7 +1177,7 @@ export const poems = [
{ {
key: '117', key: '117',
author: '', author: '',
content: ['月落星沈'], content: ['月落星沈(chén)'],
style: { style: {
backgroundImage: backgroundImage:
'linear-gradient(25deg, #688bdd, #8392c1, #9599a5, #a1a088)', 'linear-gradient(25deg, #688bdd, #8392c1, #9599a5, #a1a088)',
...@@ -1273,7 +1273,7 @@ export const poems = [ ...@@ -1273,7 +1273,7 @@ export const poems = [
{ {
key: '128', key: '128',
author: '苏轼', author: '苏轼',
content: ['麤(cū)缯大布裹生涯,腹有诗书气自华'], content: ['麤(cū)缯大布裹生涯,腹有诗书气自华'],
style: { style: {
backgroundColor: '#6A5F5C', backgroundColor: '#6A5F5C',
color: '#E18689', color: '#E18689',
......
...@@ -27,7 +27,7 @@ const { info } = useMessage(); ...@@ -27,7 +27,7 @@ const { info } = useMessage();
const source = ref(require('../media/羽肿-花火が瞬く夜に.mp3')); const source = ref(require('../media/羽肿-花火が瞬く夜に.mp3'));
const isPlaying = ref(false); const isPlaying = ref(false);
const carouselRef = ref<any>(null); const carouselRef = ref<any>(null);
const slide = ref('135'); const slide = ref('60');
onMounted(() => { onMounted(() => {
// rightClick(); // rightClick();
......
...@@ -29,31 +29,66 @@ onMounted(() => { ...@@ -29,31 +29,66 @@ onMounted(() => {
drawGrid(); drawGrid();
const pointO = { x: 600, y: 200, name: 'O' }; // const pointO = { x: 600, y: 200, name: 'O' };
const pointA = { x: 500, y: 300, name: 'A' }; // const pointA = { x: 500, y: 300, name: 'A' };
const pointB = { x: 800, y: 300, name: 'B' }; // const pointB = { x: 800, y: 300, name: 'B' };
drawVector(pointO, pointA); // drawVector(pointO, pointA);
drawVector(pointO, pointB); // drawVector(pointO, pointB);
// 加法 // // 加法
const pointC = new Vector(pointO, pointA).add(pointB) as any; // const pointC = new Vector(pointO, pointA).add(pointB) as any;
pointC.name = 'C'; // pointC.name = 'C';
const len = new Vector(pointO, pointB).length; // const len = new Vector(pointO, pointB).length;
console.log('OB向量长度', len); // console.log('OB向量长度', len);
const len2 = new Vector(pointA, pointB).length; // const len2 = new Vector(pointA, pointB).length;
console.log('AB向量的长度', len2); // console.log('AB向量的长度', len2);
drawVector(pointO, pointC, '#21BA45'); // drawVector(pointO, pointC, '#21BA45');
// 减 // // 减
const pointD = new Vector(pointO, pointB).subtract(pointA); // const pointD = new Vector(pointO, pointB).subtract(pointA);
console.log('pointD', pointD); // console.log('pointD', pointD);
drawVector(pointO, pointD, '#FFA000'); // drawVector(pointO, pointD, '#FFA000');
// 求夹角 // // 求夹角
const angle = new Vector(pointO, pointA).dotProduct(pointB); // const angle = new Vector(pointO, pointA).dotProduct(pointB);
console.log('OA向量到OB向量的夹角', angle); // console.log('OA向量到OB向量的夹角', angle);
const pointP = { x: 400, y: 200, name: 'P' };
const pointP1 = { x: 700, y: 200, name: 'P1' };
const pointP2 = { x: 300, y: 400, name: 'P2' };
drawVector(pointP, pointP1);
drawVector(pointP, pointP2);
// 单位化后的向量以(0,0)点为原点
// 单位化PP1向量
const pointP1fterUnit = new Vector(pointP, pointP1).unitization();
// 单位化PP2向量
const pointP2fterUnit = new Vector(pointP, pointP2).unitization();
const unitP1 = pointP1fterUnit.point;
const myUnitP1 = { x: unitP1.x * 100, y: unitP1.y * 100 };
const _myUnitP1 = { x: myUnitP1.x + pointP.x, y: myUnitP1.y + pointP.y };
drawVector(pointP, _myUnitP1, 'pink');
const unitP2 = pointP2fterUnit.point;
const myUnitP2 = { x: unitP2.x * 100, y: unitP2.y * 100 };
const _myUnitP2 = { x: myUnitP2.x + pointP.x, y: myUnitP2.y + pointP.y };
drawVector(pointP, _myUnitP2, 'pink');
// PQ的单位向量
// = 单位化PP1向量 + 单位化PP2向量
const unitPQ = new Vector(pointP, _myUnitP1).add(_myUnitP2);
drawVector(pointP, unitPQ, 'pink');
console.log('PQ的单位向量', unitPQ);
console.log(
'单位化PP1向量',
pointP1fterUnit,
'单位化PP2向量',
pointP2fterUnit
);
}); });
function drawVector(pointX: Point, pointY: Point, color = '#F44336') { function drawVector(pointX: Point, pointY: Point, color = '#F44336') {
......
...@@ -102,6 +102,23 @@ export class Vector { ...@@ -102,6 +102,23 @@ export class Vector {
// c向量的模 = x1*y2 - x2*y1 // c向量的模 = x1*y2 - x2*y1
// = a向量的模 * b向量的模 * sin(夹角) // = a向量的模 * b向量的模 * sin(夹角)
// 如果以向量a和向量b边构成一个平行四边形,那么这两个向量外积的模长与这个平行四边形的面积相等。 // 如果以向量a和向量b边构成一个平行四边形,那么这两个向量外积的模长与这个平行四边形的面积相等。
// 向量单位化
// 单位化后的向量以(0,0)点为原点
unitization() {
const pointO = this.components[0];
const pointA = this.components[1];
const norm = (x: number, y: number) => Math.sqrt(x * x + y * y);
const vectorX1 = pointA.x - pointO.x; // 向量OA 横坐标
const vectorY1 = pointA.y - pointO.y; // 向量OA 纵坐标
const n1 = norm(vectorX1, vectorY1); // 向量的平方根 为了对向量OA做单位化
const vectorUnitX1 = vectorX1 / n1; // 向量单位化 横坐标
const vectorUnitY1 = vectorY1 / n1; // 向量单位化 纵坐标
return {
point: { x: vectorUnitX1, y: vectorUnitY1 },
n: n1,
};
}
} }
/** /**
......
<!--
* @FileDescription: vue-konva
* @Author: hcy
* @Date: 2023-03-29
-->
<script setup lang="ts">
import { reactive, onMounted } from 'vue';
import Konva from 'konva';
import { scalePolygon } from 'src/common/utils';
import type { Points } from './types';
const state = reactive({
stage: null as any,
shapePath: [
{
name: 'test1',
color: 'pink',
path: [
{ x: 100, y: 100 },
{ x: 200, y: 100 },
{ x: 200, y: 200 },
{ x: 0, y: 300 },
],
},
] as any[],
});
const stageSize = reactive({
width: 1200, // 画布宽度
height: 800, // 画布高度
gridGap: 100, // 网格的间距
});
onMounted(() => {
drawGrid();
handleData();
//
initKonva();
});
function handleData() {
const list = state.shapePath;
for (const iter of list) {
iter.linePath = [];
iter.scalePath = [];
const path: Points[] = iter.path || [];
const scalePath = scalePolygon(path, 10) as Points[];
for (const ite of path) {
iter.linePath.push(ite.x);
iter.linePath.push(ite.y);
}
for (const ite of scalePath) {
iter.scalePath.push(ite.x);
iter.scalePath.push(ite.y);
}
}
}
function initKonva() {
const list = state.shapePath;
// 创建根节点(舞台)
state.stage = new Konva.Stage({
container: 'stage-container',
width: stageSize.width,
height: stageSize.height,
});
// 创建图层
const layer = new Konva.Layer({
name: 'my-layer',
});
// for循环创建组
for (const iter of list) {
/*
* 创建一个组,
* 将用于组合多个简单的形状。
* 变换组将变换所有的简单形状作为一个单位在一起
*/
const group = new Konva.Group({
name: iter.name,
draggable: true,
});
// 创建图形1
// points: 点坐标的平面阵列。你应该定义它们为[x1, y1, x2, y2, x3, y3]。
const poly = new Konva.Line({
name: iter.name,
points: iter.linePath,
fill: iter.color || '#00D2FF', // 填充颜色
stroke: 'black', // 边框颜色
strokeWidth: 0, // 边框宽度
closed: true, // 是否闭合路径
});
// 创建图形2-图形边框
const polygonBorder = new Konva.Line({
points: iter.scalePath,
stroke: 'green', // 边框颜色
strokeWidth: 1, // 边框宽度
closed: true, // 是否闭合路径
});
// 将图形添加到组
group.add(poly);
group.add(polygonBorder);
// 将组添加到图层中
layer.add(group);
}
// 将图层添加到根节点上
state.stage.add(layer);
}
/**
* 绘制网格线
*/
function drawGrid() {
let canvas: any = document.getElementById('canvas-grid');
let pen = canvas.getContext('2d');
// 绘制网格
const step = stageSize.gridGap;
const h = stageSize.height;
const w = stageSize.width;
const w_l = w / step;
const h_l = h / step;
// 横着的线
for (let i = 0; i <= h_l; i++) {
pen.beginPath();
pen.moveTo(0, i * step);
pen.lineTo(w, i * step);
pen.stroke();
}
// 竖着的线
for (let i = 0; i <= w_l; i++) {
pen.beginPath();
pen.moveTo(i * step, 0);
pen.lineTo(i * step, h);
pen.stroke();
}
}
function getAbsolutePosition() {
const layerList: any[] = state.stage.children; // 图层List
for (const layerItem of layerList) {
dosomethingWithLayer(layerItem);
}
}
/**
* Class: Layer
* https://konvajs.org/api/Konva.Layer.html
* 图层的构造函数。图层绑定到它们自己的canvas元素,并用于包含组或图形。
*/
function dosomethingWithLayer(layer: any) {
// 获取图层位置
// const position = layer.absolutePosition();
// 设置图层位置
// layer.absolutePosition({
// x: 5,
// y: 10,
// });
const groupList: any[] = layer.children; // 组List
for (const groupItem of groupList) {
dosomethingWithGroup(groupItem);
}
}
/**
* Class: Group
* https://konvajs.org/api/Konva.Group.html
* 组的构造函数。组用于包含图形或其它组。
*/
function dosomethingWithGroup(group: any) {
// 获取组的位置
// const position = group.absolutePosition();
// const diagramList: any[] = group.children;
const diagramList = group.getChildren();
// const clientRect = group.getClientRect();
for (const diagramItem of diagramList) {
dosomethingWithDiagram(diagramItem);
}
}
function dosomethingWithDiagram(diagram: any) {
const attrs = diagram.getAttrs();
console.log('attrs', attrs);
}
</script>
<template>
<div class="konva-main-page container-height center">
<div>
<q-btn
color="primary"
label="获取坐标位置"
@click="getAbsolutePosition"
/>
</div>
<div
class="canvas-box"
:style="{
width: stageSize.width + 'px',
height: stageSize.height + 'px',
}"
>
<canvas
id="canvas-grid"
:width="stageSize.width"
:height="stageSize.height"
style="position: absolute"
></canvas>
<div id="stage-container"></div>
</div>
</div>
</template>
<style lang="scss" scoped>
.canvas-box {
box-sizing: border-box;
border: 1px solid #000;
position: relative;
}
</style>
<!--
* @FileDescription: vue-konva
* @Author: hcy
* @Date: 2023-03-29
-->
<script setup lang="ts">
import { reactive, onMounted } from 'vue';
import Konva from 'konva';
import type { Points } from './types';
const state = reactive({
stage: null as any,
shapePath: [
{
name: 'test1',
color: 'pink',
path: [
{ x: 100, y: 100 },
{ x: 200, y: 100 },
{ x: 200, y: 200 },
{ x: 0, y: 300 },
],
},
] as any[],
});
const stageSize = reactive({
width: 1200, // 画布宽度
height: 800, // 画布高度
gridGap: 100, // 网格的间距
});
onMounted(() => {
drawGrid();
handleData();
initKonva();
});
function handleData() {
const list = state.shapePath;
for (const iter of list) {
iter.linePath = [];
const path: Points[] = iter.path || [];
for (const ite of path) {
iter.linePath.push(ite.x);
iter.linePath.push(ite.y);
}
}
}
function initKonva() {
const list = state.shapePath;
console.log(list);
// 创建根节点(舞台)
state.stage = new Konva.Stage({
container: 'stage-container',
width: stageSize.width,
height: stageSize.height,
});
// 创建图层
const layer = new Konva.Layer({
name: 'my-layer',
});
/*
* 创建一个组,
* 将用于组合多个简单的形状。
* 变换组将变换所有的简单形状作为一个单位在一起
*/
const group = new Konva.Group({
name: 'my-group',
draggable: true,
});
// 创建图形
// points: 点坐标的平面阵列。你应该定义它们为[x1, y1, x2, y2, x3, y3]。
const poly = new Konva.Line({
name: 'my-poly',
points: [100, 100, 300, 200, 500, 200, 500, 300, 400, 400, 100, 400],
fill: '#00D2FF', // 填充颜色
stroke: 'black', // 边框颜色
strokeWidth: 0, // 边框宽度
closed: true, // 是否闭合路径
});
// const line = new Konva.Line({
// name: 'my-line',
// x: 0,
// y: 0,
// points: [300, 100, 500, 100, 500, 200, 300, 200],
// stroke: 'red',
// closed: true,
// });
// 将图形添加到组
group.add(poly);
// group.add(line);
// 将组添加到图层中
layer.add(group);
// 将图层添加到根节点上
state.stage.add(layer);
}
/**
* 绘制网格线
*/
function drawGrid() {
let canvas: any = document.getElementById('canvas-grid');
let pen = canvas.getContext('2d');
// 绘制网格
const step = stageSize.gridGap;
const h = stageSize.height;
const w = stageSize.width;
const w_l = w / step;
const h_l = h / step;
// 横着的线
for (let i = 0; i <= h_l; i++) {
pen.beginPath();
pen.moveTo(0, i * step);
pen.lineTo(w, i * step);
pen.stroke();
}
// 竖着的线
for (let i = 0; i <= w_l; i++) {
pen.beginPath();
pen.moveTo(i * step, 0);
pen.lineTo(i * step, h);
pen.stroke();
}
}
function getAbsolutePosition() {
const layerList: any[] = state.stage.children; // 图层List
for (const layerItem of layerList) {
dosomethingWithLayer(layerItem);
}
}
/**
* Class: Layer
* https://konvajs.org/api/Konva.Layer.html
* 图层的构造函数。图层绑定到它们自己的canvas元素,并用于包含组或图形。
*/
function dosomethingWithLayer(layer: any) {
// 获取图层位置
// const position = layer.absolutePosition();
// 设置图层位置
// layer.absolutePosition({
// x: 5,
// y: 10,
// });
const groupList: any[] = layer.children; // 组List
for (const groupItem of groupList) {
dosomethingWithGroup(groupItem);
}
}
/**
* Class: Group
* https://konvajs.org/api/Konva.Group.html
* 组的构造函数。组用于包含图形或其它组。
*/
function dosomethingWithGroup(group: any) {
// 获取组的位置
// const position = group.absolutePosition();
// const diagramList: any[] = group.children;
const diagramList = group.getChildren();
// const clientRect = group.getClientRect();
for (const diagramItem of diagramList) {
dosomethingWithDiagram(diagramItem);
}
}
function dosomethingWithDiagram(diagram: any) {
const attrs = diagram.getAttrs();
console.log('attrs', attrs);
}
</script>
<template>
<div class="konva-main-page container-height center">
<div>
<q-btn
color="primary"
label="获取坐标位置"
@click="getAbsolutePosition"
/>
</div>
<div
class="canvas-box"
:style="{
width: stageSize.width + 'px',
height: stageSize.height + 'px',
}"
>
<canvas
id="canvas-grid"
:width="stageSize.width"
:height="stageSize.height"
style="position: absolute"
></canvas>
<div id="stage-container"></div>
</div>
</div>
</template>
<style lang="scss" scoped>
.canvas-box {
box-sizing: border-box;
border: 1px solid #000;
position: relative;
}
</style>
export default [
{
path: 'vue-konva-line',
name: 'VUE_KONVA_LINE',
component: () => import('./IndexPage.vue'),
meta: {
title: 'Line-多边形',
permission: ['*'],
keepalive: true,
},
},
];
export interface Points {
x: number;
y: number;
[proppName: string]: any;
}
...@@ -26,10 +26,10 @@ const state = reactive({ ...@@ -26,10 +26,10 @@ const state = reactive({
color: '#00D2FF', color: '#00D2FF',
selected: true, selected: true,
path: [ path: [
{ x: 100, y: 100, gap: 100 }, { x: 100, y: 100, gap: 10 },
{ x: 200, y: 100, gap: 100 }, { x: 200, y: 100, gap: 20 },
{ x: 200, y: 200, gap: 100 }, { x: 200, y: 200, gap: 30 },
{ x: 0, y: 300, gap: 100 }, { x: 0, y: 300, gap: 40 },
], ],
}, },
// { // {
......
<!--
* @FileDescription: vue-konva
* @Author: hcy
* @Date: 2023-03-29
-->
<script setup lang="ts">
import { reactive, onMounted } from 'vue';
// import Konva from 'konva';
// const state = reactive({
// stage: null as any,
// layer: null as any,
// group: new Map(),
// myMap: new Map(),
// // shape: null as any,
// // boundingBox: null as any,
// // box: null as any,
// shapePath: [
// {
// name: 'test1',
// color: 'pink',
// selected: true,
// path: [
// { x: 100, y: 100 },
// { x: 200, y: 100 },
// { x: 200, y: 200 },
// { x: 0, y: 300 },
// ],
// },
// ] as any[],
// });
const stageSize = reactive({
width: 1200, // 画布宽度
height: 800, // 画布高度
gridGap: 100, // 网格的间距
});
onMounted(() => {
drawGrid();
});
/**
* 绘制网格线
*/
function drawGrid() {
let canvas: any = document.getElementById('canvas-grid');
let pen = canvas.getContext('2d');
// 绘制网格
const step = stageSize.gridGap;
const h = stageSize.height;
const w = stageSize.width;
const w_l = w / step;
const h_l = h / step;
// 横着的线
for (let i = 0; i <= h_l; i++) {
pen.beginPath();
pen.moveTo(0, i * step);
pen.lineTo(w, i * step);
pen.stroke();
}
// 竖着的线
for (let i = 0; i <= w_l; i++) {
pen.beginPath();
pen.moveTo(i * step, 0);
pen.lineTo(i * step, h);
pen.stroke();
}
}
</script>
<template>
<div class="konva-main-page container-height center">
<div
class="canvas-box"
:style="{
width: stageSize.width + 'px',
height: stageSize.height + 'px',
}"
>
<canvas
id="canvas-grid"
:width="stageSize.width"
:height="stageSize.height"
style="position: absolute"
></canvas>
<div id="stage-container"></div>
</div>
</div>
</template>
<style lang="scss" scoped>
.canvas-box {
box-sizing: border-box;
border: 1px solid #000;
position: relative;
}
</style>
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
* 源码Gitee:https://gitee.com/dhzx/js-polygon-algorithm * 源码Gitee:https://gitee.com/dhzx/js-polygon-algorithm
*/ */
import { toRadian, Vector } from 'src/modules/vector/utils'; // import { toRadian, Vector } from 'src/modules/vector/utils';
interface Point { interface Point {
x: number; x: number;
...@@ -177,6 +177,7 @@ export function scalePolygon(points: Point[]) { ...@@ -177,6 +177,7 @@ export function scalePolygon(points: Point[]) {
const ps = points; const ps = points;
const len = ps.length; const len = ps.length;
const polygon: any[] = []; const polygon: any[] = [];
const is_clockwise = isClockwise(ps);
for (let i = 0; i < len; i++) { for (let i = 0; i < len; i++) {
const pointP = ps[i]; // 当前点 const pointP = ps[i]; // 当前点
...@@ -184,16 +185,10 @@ export function scalePolygon(points: Point[]) { ...@@ -184,16 +185,10 @@ export function scalePolygon(points: Point[]) {
const pointP2 = ps[i === 0 ? len - 1 : i - 1]; // 前一个点 const pointP2 = ps[i === 0 ? len - 1 : i - 1]; // 前一个点
// 边距 // 边距
const extraNum = pointP.gap || 10; const extraNum = 20;
// 通过顺时针判断取正值还是负值 // 通过顺时针判断取正值还是负值
const is_clockwise = isClockwise(ps);
const extra0 = is_clockwise ? -extraNum : extraNum; const extra0 = is_clockwise ? -extraNum : extraNum;
// const l1Num = pointP.gap || 10;
// const l2Num = pointP2.gap || 10;
// const L1 = is_clockwise ? -l1Num : l1Num;
// const L2 = is_clockwise ? -l2Num : l2Num;
// 向量PP1 // 向量PP1
const vectorX1 = pointP1.x - pointP.x; // 向量PP1 横坐标 const vectorX1 = pointP1.x - pointP.x; // 向量PP1 横坐标
const vectorY1 = pointP1.y - pointP.y; // 向量PP1 纵坐标 const vectorY1 = pointP1.y - pointP.y; // 向量PP1 纵坐标
...@@ -208,6 +203,10 @@ export function scalePolygon(points: Point[]) { ...@@ -208,6 +203,10 @@ export function scalePolygon(points: Point[]) {
let vectorUnitX2 = vectorX2 / n2; // 向量单位化 横坐标 let vectorUnitX2 = vectorX2 / n2; // 向量单位化 横坐标
let vectorUnitY2 = vectorY2 / n2; // 向量单位化 纵坐标 let vectorUnitY2 = vectorY2 / n2; // 向量单位化 纵坐标
const vectorUnit1 = { x: vectorUnitX1, y: vectorUnitY1 };
const vectorUnit2 = { x: vectorUnitX2, y: vectorUnitY2 };
console.log('PP1的单位向量', vectorUnit1, 'PP2的单位向量', vectorUnit2);
// PQ距离 // PQ距离
const vectorLen = const vectorLen =
extra0 / extra0 /
...@@ -215,11 +214,6 @@ export function scalePolygon(points: Point[]) { ...@@ -215,11 +214,6 @@ export function scalePolygon(points: Point[]) {
(1 - (vectorUnitX1 * vectorUnitX2 + vectorUnitY1 * vectorUnitY2)) / 2 (1 - (vectorUnitX1 * vectorUnitX2 + vectorUnitY1 * vectorUnitY2)) / 2
); );
const angle = new Vector(pointP, pointP1).dotProduct(pointP2);
const hudu = toRadian(angle);
const c = Math.cos(hudu);
console.log('PQ距离', vectorLen, '角度', c);
// 根据向量的叉乘积来判断角是凹角还是凸角 // 根据向量的叉乘积来判断角是凹角还是凸角
if (vectorX1 * vectorY2 + -1 * vectorY1 * vectorX2 < 0) { if (vectorX1 * vectorY2 + -1 * vectorY1 * vectorX2 < 0) {
vectorUnitX2 *= -1; vectorUnitX2 *= -1;
......
...@@ -6,6 +6,7 @@ import AMIS from '../modules/amis/route'; ...@@ -6,6 +6,7 @@ import AMIS from '../modules/amis/route';
import VUE_STUDY from '../modules/vue-study/route'; import VUE_STUDY from '../modules/vue-study/route';
import VUE_KONVA from '../modules/vue-konva/route'; import VUE_KONVA from '../modules/vue-konva/route';
import VECTOR from '../modules/vector/route'; import VECTOR from '../modules/vector/route';
import VUE_KONVA_LINE from '../modules/vue-konva-line/route';
const routes: RouteRecordRaw[] = [ const routes: RouteRecordRaw[] = [
{ {
...@@ -135,6 +136,7 @@ const routes: RouteRecordRaw[] = [ ...@@ -135,6 +136,7 @@ const routes: RouteRecordRaw[] = [
...VUE_STUDY, ...VUE_STUDY,
...VUE_KONVA, ...VUE_KONVA,
...VECTOR, ...VECTOR,
...VUE_KONVA_LINE,
], ],
}, },
], ],
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment