5.7k sao GitHub và vẫn tăng — steveruizok/perfect-freehand là dự án HTML mà TopGit đang theo dõi trên nền tảng. Draw perfect pressure-sensitive freehand lines.
Tóm tắt dựng từ metadata GitHub của chính dự án — chưa có bài review TopGit. Trang sẽ tự động cập nhật khi bài review đầy đủ được xuất bản.
VÌ SAO CHƯA CÓ REVIEW
TopGit viết bài đầy đủ cho repo có nhiều sao nhất và được yêu cầu nhiều nhất. Trang này là snapshot trong thời gian chờ — xem README gốc ở tab READ ME.
🕊 This library is written in TypeScript but are community ports in:
dart version
odin
python
rust
...and probably more. Make a pull request!
💕 Love this library? Consider becoming a sponsor.
Table of Contents
Installation
Usage
Documentation
Community
Author
Installation
npm install perfect-freehand
or
yarn add perfect-freehand
Introduction
This package exports a function named getStroke that will generate the points for a polygon based on an array of points.
To do this work, getStroke first creates a set of spline points (red) based on the input points (grey) and then creates outline points (blue). You can render the result any way you like, using whichever technology you prefer.
Usage
To use this library, import the getStroke function and pass it an array of input points, such as those recorded from a user's mouse movement. The getStroke function will return a new array of outline points. These outline points will form a polygon (called a "stroke") that surrounds the input points.
You then can render your stroke points using your technology of choice. See the Rendering section for examples in SVG and HTML Canvas.
You can customize the appearance of the stroke shape by passing getStroke a second parameter: an options object containing one or more options. See the Options section for a full list of available options.
The appearance of a stroke is effected by the pressure associated with each input point. By default, the getStroke function will simulate pressure based on the distance between input points.
To use real pressure, such as that from a pen or stylus, provide the pressure as the third number for each input point, and set the simulatePressure option to false.
In addition to providing points as an array of arrays, you may also provide your points as an array of objects as show in the example below. In both cases, the value for pressure is optional (it will default to .5).
Note: Internally, the getStroke function will convert your object points to array points, which will have an effect on performance. If you're using this library ambitiously and want to format your points as objects, consider modifying this library's getStrokeOutlinePoints to use the object syntax instead (e.g. replacing all [0] with .x, [1] with .y, and [2] with .pressure).
Tip: To create a stroke with a steady line, set the thinning option to 0.
Tip: To create a stroke that gets thinner with pressure instead of thicker, use a negative number for the thinning option.
Other Exports
For advanced usage, the library also exports smaller functions that getStroke uses to generate its outline points.
getStrokePoints
A function that accepts an array of points (formatted either as [x, y, pressure] or { x: number, y: number, pressure: number}) and (optionally) an options object. Returns a set of adjusted points as { point, pressure, vector, distance, runningLength }. The path's total length will be the runningLength of the last point in the array.
import { getStrokePoints } from 'perfect-freehand'
import samplePoints from "./samplePoints.json'
const strokePoints = getStrokePoints(samplePoints)
getStrokeOutlinePoints
A function that accepts an array of points (formatted as { point, pressure, vector, distance, runningLength }, i.e. the output of getStrokePoints) and (optionally) an options object, and returns an array of points ([x, y]) defining the outline of a pressure-sensitive stroke.
import { getStrokePoints, getStrokeOutlinePoints } from 'perfect-freehand'
import samplePoints from "./samplePoints.json'
const strokePoints = getStrokePoints(samplePoints)
const outlinePoints = getStrokeOutlinePoints(strokePoints)
Note: Internally, the getStroke function passes the result of getStrokePoints to getStrokeOutlinePoints, just as shown in this example. This means that, in this example, the result of outlinePoints will be the same as if the samplePoints array had been passed to getStroke.
StrokeOptions
A TypeScript type for the options object. Useful if you're defining your options outside of the getStroke function.
While this library was designed for rendering the types of input points generated by the movement of a human hand, you can pass any set of points into the library's functions. For example, here's what you get when running Feather Icons through getStroke.
Rendering
While getStroke returns an array of points representing the outline of a stroke, it's up to you to decide how you will render these points.
The function below will turn the points returned by getStroke into SVG path data.
const average = (a, b) => (a + b) / 2
function getSvgPathFromStroke(points, closed = true) {
const len = points.length
if (len < 4) {
return ``
}
let a = points[0]
let b = points[1]
const c = points[2]
let result = `M${a[0].toFixed(2)},${a[1].toFixed(2)} Q${b[0].toFixed(
2
)},${b[1].toFixed(2)} ${average(b[0], c[0]).toFixed(2)},${average(
b[1],
c[1]
).toFixed(2)} T`
for (let i = 2, max = len - 1; i < max; i++) {
a = points[i]
b = points[i + 1]
result += `${average(a[0], b[0]).toFixed(2)},${average(a[1], b[1]).toFixed(
2
)} `
}
if (closed) {
result += 'Z'
}
return result
}
To use this function, first run your input points through getStroke, then pass the result to getSvgPathFromStroke.
You could then pass this string of SVG path data either to an SVG path element:
<path d={pathData} />
Or, if you are rendering with HTML Canvas, you can pass the string to a Path2D constructor).
const myPath = new Path2D(pathData)
ctx.fill(myPath)
Flattening
By default, the polygon's paths include self-crossings. You may wish to remove these crossings and render a stroke as a "flattened" polygon. To do this, install the polygon-clipping package and use the following function together with the getSvgPathFromStroke.
import polygonClipping from 'polygon-clipping'
function getFlatSvgPathFromStroke(stroke) {
const faces = polygonClipping.union([stroke])
const d = []
faces.forEach((face) =>
face.forEach((points) => {
d.push(getSvgPathFromStroke(points))
})
)
return d.join(' ')
}
Development & Contributions
To work on this library:
clone this repo
run yarn in the folder root to install dependencies
run yarn start to start the local development server
The development server is located at packages/dev. The library and its tests are located at packages/perfect-freehand.
Pull requests are very welcome!
Community
Support
Need help? Please open an issue for support.
Discussion
Have an idea or casual question? Visit the discussion page.
License
MIT
...but if you're using perfect-freehand in a commercial product, consider becoming a sponsor. 💰
steveruizok/perfect-freehand thuộc nhóm Image Tools trên TopGit, cùng 8 topic GitHub. Trang Trending và Topics liệt kê các repo cùng số sao và cùng ngôn ngữ để so sánh.
Đọc thêm về steveruizok/perfect-freehand ở đâu?
Trang TopGit này là một snapshot — tab "Readme" hiển thị nguyên văn README của repo (đã bỏ link, giữ ảnh). Repo GitHub ở github.com/steveruizok/perfect-freehand là nguồn chính thức.
steveruizok/perfect-freehand có bao nhiêu sao?
steveruizok/perfect-freehand có 5.7k sao GitHub — tải lại trang để xem số mới nhất, hoặc xem trực tiếp github.com/steveruizok/perfect-freehand. TopGit phản chiếu số sao của GitHub nhưng không cam kết đến từng phút.
steveruizok/perfect-freehand có những chủ đề gì?
GitHub topics của steveruizok/perfect-freehand: "drawing", "graphics", "html-canvas", "lines", "pressure", "stroke", "svg", "variable-width". TopGit xếp repo vào nhóm Image Tools.
steveruizok/perfect-freehand có phải mã nguồn mở không?
Có — steveruizok/perfect-freehand phát hành theo license MIT, nghĩa là mã nguồn mở để đọc, fork và (tùy license) tái sử dụng. Mã: github.com/steveruizok/perfect-freehand.
steveruizok/perfect-freehand có trang demo không?
Dự án có trang chủ ở https://perfectfreehand.com. Tab "Readme" ở trang này thường có ảnh chụp và hướng dẫn bắt đầu nhanh.
steveruizok/perfect-freehand còn đang phát triển không?
Commit gần nhất trên steveruizok/perfect-freehand là 4 tháng trước (theo timestamp GitHub). Repo có 212 fork — một chỉ báo về mức độ quan tâm của cộng đồng.
Đọc đầy đủ README ở tab phía trên.
Vẫn đang phân vân về perfect-freehand?
Một cú bấm sẽ gửi câu hỏi kèm trang này cho AI — xem AI nói gì về perfect-freehand.