Giter VIP home page Giter VIP logo

util's Introduction

util

AntV 底层依赖的工具库,不建议在自己业务中使用。

Build Status npm Version npm Download npm License

Usage

import { gradient } from '@antv/util';

原则

  • util 只有一个 npm 包,按照目录来组织不同类型的方法,避免 monorepo 互相依赖
  • 内容和 AntV 强相关,避免做和 lodash 等相同的工具库
  • 不使用的方法,及时删除,并保持新增方法可以按需引入
  • 旧版本的不维护,如果 AntV 技术栈的旧版本需要迭代,请升级到 v3

API

提供以下 Path 工具方法,包含转换、几何计算等。

path2String

将 PathArray 转换成字符串形式,不会对原始定义中的命令进行修改:

const str: PathArray = [
  ['M', 10, 10],
  ['L', 100, 100],
  ['l', 10, 10],
  ['h', 20],
  ['v', 20],
];
expect(path2String(str)).toEqual('M10 10L100 100l10 10h20v20');

path2Array

将 PathArray 转换成数组,不会对原始定义中的命令进行修改:

const str = 'M10 10L100 100l10 10h20v20';
expect(path2Array(str)).toEqual([
  ['M', 10, 10],
  ['L', 100, 100],
  ['l', 10, 10],
  ['h', 20],
  ['v', 20],
]);

path2Absolute

将定义中的相对命令转换成绝对命令,例如:

  • l -> L
  • h -> H
  • v -> V

完整方法签名如下:

path2Absolute(pathInput: string | PathArray): AbsoluteArray;
const str: PathArray = [
  ['M', 10, 10],
  ['L', 100, 100],
  ['l', 10, 10],
  ['h', 20],
  ['v', 20],
];
const arr = path2Absolute(str);
expect(arr).toEqual([
  ['M', 10, 10],
  ['L', 100, 100],
  ['L', 110, 110],
  ['H', 130],
  ['V', 130],
]);

path2Curve

将部分命令转曲,例如 L / A 转成 C 命令,借助 cubic bezier 易于分割的特性用于实现形变动画。 该方法内部会调用 path2Absolute,因此最终返回的 PathArray 中仅包含 M 和 C 命令。

完整方法签名如下:

path2Curve(pathInput: string | PathArray): CurveArray;
expect(
  path2Curve([
    ['M', 0, 0],
    ['L', 100, 100],
  ]),
).toEqual([
  ['M', 0, 0],
  ['C', 44.194173824159215, 44.194173824159215, 68.75, 68.75, 100, 100],
]);

clonePath

复制路径:

const cloned = clonePath(pathInput);

reverseCurve

const pathArray: CurveArray = [
  ['M', 170, 90],
  ['C', 150, 90, 155, 10, 130, 10],
  ['C', 105, 10, 110, 90, 90, 90],
  ['C', 70, 90, 75, 10, 50, 10],
  ['C', 25, 10, 30, 90, 10, 90],
];

const reversed = reverseCurve(pathArray);

getPathBBox

获取几何定义下的包围盒,形如:

export interface PathBBox {
  width: number;
  height: number;
  x: number;
  y: number;
  x2: number;
  y2: number;
  cx: number;
  cy: number;
  cz: number;
}
const bbox = getPathBBox([['M', 0, 0], ['L', 100, 0], ['L', 100, 100], ['L', 0, 100], ['Z']]);

expect(bbox).toEqual({ cx: 50, cy: 50, cz: 150, height: 100, width: 100, x: 0, x2: 100, y: 0, y2: 100 });

getTotalLength

获取路径总长度。

const length = getTotalLength([['M', 0, 0], ['L', 100, 0], ['L', 100, 100], ['L', 0, 100], ['Z']]);

expect(length).toEqual(400);

getPointAtLength

获取路径上从起点出发,到指定距离的点。

const point = getPointAtLength([['M', 0, 0], ['L', 100, 0], ['L', 100, 100], ['L', 0, 100], ['Z']], 0);
expect(point).toEqual({ x: 0, y: 0 });

getPathArea

计算路径包围的面积。内部实现中首先通过 path2Curve 转曲,再计算 cubic curve 面积,详见

方法签名如下:

function getPathArea(path: PathArray): number;

isPointInStroke

判断一个点是否在路径上,仅通过几何定义计算,不考虑其他样式属性例如线宽、lineJoin、miter 等。

方法签名如下:

isPointInStroke(pathInput: string | PathArray, point: Point): boolean;
const result = isPointInStroke(segments, { x: 10, y: 10 });

distanceSquareRoot

计算两点之间的距离。

方法签名如下:

distanceSquareRoot(a: [number, number], b: [number, number]): number;

equalizeSegments

将两条路径处理成段数相同,用于形变动画前的分割操作。

const [formattedPath1, formattedPath2] = equalizeSegments(path1, path2);

isPointInPolygon

判断一个点是否在多边形内。多边形形如:

const polygon = [
  [0, 0],
  [0, 100],
  [30, 100],
  [30, 0],
];

// [0, 0] 在多边形的边上
isPointInPolygon(polygon, 0, 0); // true

isPolygonsIntersect

判断两个多边形是否相交:

isPolygonsIntersect(polygon1, polygon2);

License

MIT@AntV.

util's People

Contributors

1wkk avatar heiyexing avatar hustcc avatar xiaoiver avatar yanyan-wang avatar zweifisch avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

util's Issues

path-util 不支持 m 命令

路径中包含 m 命令时,转成绝对路径(path2Absolute)时会报错,例如下面的路径转绝对值时会得到一个错误的结果:

const path = [
      ['M', 120, 100],
      ['L', 200, 200],
      ['m', 120, 100],
      ['L', 200, 200],
];

const absolutePath = [
      ['M', 120, 100],
      ['L', 200, 200],
      ['M'], // 错误的 segment
      ['L', 200, 200],
];

path-util 中计算三次贝塞尔曲线切线有误

以下计算切线方法未考虑控制点与起点/终点重合的情况:

// 起点与控制点1
segment.startTangent = [prePoint[0] - cp1[0], prePoint[1] - cp1[1]];
// 终点与控制点2
segment.endTangent = [currentPoint[0] - cp2[0], currentPoint[1] - cp2[1]];

导致计算水平直线时,会得到 [0, 0]
['C', 100, 100, 100, 100, 200, 200]

正确做法应该是判定重合时,使用两个控制点计算:

if (segment.startTangent[0] === 0 && segment.startTangent[1] === 0) {
    segment.startTangent = [cp1[0] - cp2[0], cp1[1] - cp2[1]];
}
if (segment.endTangent[0] === 0 && segment.endTangent[1] === 0) {
    segment.endTangent = [cp2[0] - cp1[0], cp2[1] - cp1[1]];
}

潜在的原型链污染漏洞

复现代码1:

let deepMix = require("@antv/util").deepMix;

let BAD_JSON = JSON.parse('{"__proto__":{"test":123}}');

let obj = {};
deepMix(obj, BAD_JSON);

console.log({}.test); // 123

问题代码:

const deepMix = function (rst: any, ...args: any[]) {
for (let i = 0; i < args.length; i += 1) {
_deepMix(rst, args[i]);
}
return rst;
};

复现代码2:

let set = require("@antv/util").set;

let obj = {};
set(obj, "__proto__.test", 123);

console.log({}.test); // 123

问题代码:

util/src/lodash/set.ts

Lines 5 to 29 in c499a30

/**
* https://github.com/developit/dlv/blob/master/index.js
* @param obj
* @param path
* @param value
*/
export default (obj: any, path: string | any[], value: any): any => {
let o = obj;
const keyArr = isString(path) ? path.split('.') : path;
keyArr.forEach((key: string | number, idx: number) => {
// 不是最后一个
if (idx < keyArr.length - 1) {
if (!isObject(o[key])) {
o[key] = isNumber(keyArr[idx + 1]) ? [] : {};
}
o = o[key];
} else {
o[key] = value;
}
});
return obj;
};

webpack5 打包出现警告

警告内容如下:
WARNING in ./node_modules/@antv/matrix-util/esm/vec2.js 30:0-13
export 'vertical' (imported as 'vec2') was not found in '@antv/gl-matrix/lib/gl-matrix/vec2' (possible exports: __esModule, add, angle, ceil, clone, copy, create, cross, dist, distance, div, divide, dot, equals, exactEquals, floor, forEach, fromValues, inverse, len, length, lerp, max, min, mul, multiply, negate, normalize, random, rotate, round, scale, scaleAndAdd, set, sqrDist, sqrLen, squaredDistance, squaredLength, str, sub, subtract, transformMat2, transformMat2d, transformMat3, transformMat4)
@ ./node_modules/@antv/matrix-util/esm/index.js 3:0-41 3:0-41

如图
image

经过我多次查看,还原,发现问题在于matrix-util/esm/index.js的export语法用法不太对
image

export { default as vec2 } from './vec2';

这样的导出语句相当于

import {vec2} from './vec2';
export default vec2;

所有会报警告 vec2 not found

版本更新到 最新版本发现解决

Error import module with TypeScript

in this section from 'node_module/@antv/g-base/lib/animate/timeline.js'

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var util_1 = require("@antv/util");
var d3Timer = require("d3-timer");
var d3_interpolate_1 = require("d3-interpolate"); // 目前整体动画只需要数值和数组的差值计算

show Error [ERR_REQUIRE_ESM] using SSR
Here is the detail of the error
image

could be changed to to correct it

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var util_1 = require("@antv/util");
var d3Timer = require("d3-timer");
const d3_interpolate_1 = async () => {
    const { interpolate } = await import("d3-interpolate");
    return interpolate;
};

node 18.12.1

using in node.js

require('@antv/util') is throwing error due to usage of Global Variables in browser environment

如何引入util的js文件?

如同下面的html

  <head>
    <script src="https://gw.alipayobjects.com/os/lib/antv/g6/4.3.11/dist/g6.min.js"></script>
  </head>

如何在页面引入util的js文件

出现大量文件路径错误

Failed to parse source map from '/Users/felix/Documents/MobileWork/work/数据大屏/tsrsdv/scene_drill/node_modules/@antv/util/esm/path/convert/src/path/convert/path-2-absolute.ts' file: Error: ENOENT: no sfile or directory, open '/Users/felix/Documents/MobileWork/work/数据大屏/tsrsdv/scene_drill/node_modules/@antv/util/esm/path/convert/src/path/convert/path-2-absolute.ts'

底下还有很多很多

在安装后,使用就会出现大量这样的路径错误。

下面是复现问题的步骤:

yarn create react-app scene --template typescript
cd scene
yarn add @antv/util

修改 App.tsx 文件:

import React from 'react';
import logo from './logo.svg';
import './App.css';
// 添加一行
import { gradient } from '@antv/util';

function App() {
  // 添加另一行
  console.log('gradient',gradient)
  return (
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <p>
          Edit <code>src/App.tsx</code> and save to reload.
        </p>
        <a
          className="App-link"
          href="https://reactjs.org"
          target="_blank"
          rel="noopener noreferrer"
        >
          Learn React
        </a>
      </header>
    </div>
  );
}

export default App;

之后执行 yarn start 命令就可以看见大量 .ts 找不到了。

好像不影响使用,只是日志很长,看不见 On Your Network 了。

在 svg-path-commander 2.0 中,lineToCubic更新为了一个更简单的算法

在 svg-path-commander 2.0 中,lineToCubic更新为了一个更简单的算法:
thednp/svg-path-commander@1757702#diff-a7563e18ea440e76d4aa2b638cd044a860e08c1e297ddbc8745fdc296d808e82

现在这个算法我觉得挺合理的,因为事先不知道line变成cubic后要去变换成的曲线是什么样子的,所以事先去精细的计算两个控制点的分位似乎没必要是一种过度优化,只要在线段上就行了(各在1/3, 2/3分位似乎也挺好?)

老实说,它之前那个算法为什么要大费周章从p0算到p6的我不太理解,而且传入segmentLineFactory的参数数目都对不上(我看到你们截取了前面几个数目对上了,但似乎含义还是对不上)

path-util 转三次贝塞尔曲线方法有误

为了方便地计算包围盒、路径长度以及后续形变动画,我们会将路径各个命令(L、A、Q)转成 C(三次贝塞尔曲线)。

其中 A 命令转换存在问题,导致绘制效果有误:
截屏2021-09-07 下午4 15 33

segmentArcFactory 分段过多导致计算耗时

Path 部分有两点需要优化:

  • 计算 Arc 的包围盒与长度时,目前会分成 100 段,导致耗时很大。合理的做法是提供 sampleSize 参数,这样当需要高精度时就增加分段,反之可以减少
  • 目前 getPathBBoxTotalLength() 是一个二合一的方法,但有时仅需要计算包围盒或者长度。例如初始化 Path 时仅需要包围盒,此时计算长度就会造成浪费。可以通过参数控制,例如:
// 仅计算包围盒
const { x, y, width, height } = getPathBBoxTotalLength(absolutePath, { bbox: true, length: false });

// 计算时减少采样数,牺牲精度提升性能
const { x, y, width, height } = getPathBBoxTotalLength(absolutePath, { bbox: true, length: false, sampleSize: 10 });

另外需要性能测试。

getPointAtLength 计算有误,且命中后应提前终止

该方法与 SVG 同名方法保持一致,返回 Path 指定距离处的点:
https://developer.mozilla.org/zh-CN/docs/Web/API/SVGGeometryElement/getPointAtLength

在计算 A / C / Q 这样的曲线时,使用分段逼近的方法,段数越多得到的点自然越精确,在计算总长度时也会越精确,但显然性能就会下降。

目前的实现有两个问题:

  1. 在判定距离是否满足要求时未考虑相等的情况,例如下面的路径虽然使用了 Q,但实际是一条直线:
[
  ["M", 968, 400],
  ["Q", 913, 400, 858, 400]
]
  1. 命中后未提前终止,导致后续分段的计算实际都是多余的,除非需要计算整个路径的长度。

钉钉工作台组件 引入 @antv/f2-my 打包报错 @antv/util/lib/type/is-nil未找到

具体版本号 "@antv/f2-my": "^4.0.19"

钉钉工作台组件 引入 @antv/f2-my 打包报错 @antv/util/lib/type/is-nil未找到,请检查package.json配置

在使用F2的时候,报找不到依赖的问题,跟这个库有关吗?
./plugin/node_modules/@antv/f2/node_modules/@antv/adjust/lib/stack.js
@antv/util/lib/type/is-nil未找到,请检查package.json配置,并尝试重新安装node_modules依赖

./plugin/node_modules/@antv/f2/node_modules/@antv/adjust/lib/symmetric.js
@antv/util/lib/type/is-array未找到,请检查package.json配置,并尝试重新安装node_modules依赖

./plugin/node_modules/@antv/f2/node_modules/@antv/adjust/lib/symmetric.js
@antv/util/lib/math/max-by未找到,请检查package.json配置,并尝试重新安装node_modules依赖

哪里可以找到util.js文件?where can i find util.js?

在网上没有找到util.js。 我不熟悉npm,现在通过cnpm下载了util包在本地。我希望能把这个包变成util.js,以便可以在html中通过<script>引入,应该怎么做?

以及所有的需要@antv/。。引入的模块的js版本在哪里可以找到?

index.d.ts中未导出min、max的定义

如下图所示,在g-base中使用了max、min方法,但是在util中未导出其定义
Snipaste_2021-05-11_23-31-34
因此,渲染图形时报TypeError: Object(...) is not a function错误
Snipaste_2021-05-11_23-43-16
image

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.