Updated Path

* Added NewPath and NewPathFromSvg methods to Canvas interface
* Removed NewPath function
* Removed Reset methods from Path interface
This commit is contained in:
Alexei Anoshenko 2024-08-20 20:01:26 +03:00
parent 2708c7ceb6
commit 87148836c0
15 changed files with 109 additions and 50 deletions

View File

@ -5,6 +5,9 @@
* Added "transform" property and Transform interface
* Added OpenRawResource function
* Added RemoveClientItem method to Session interface
* Added NewPath and NewPathFromSvg methods to Canvas interface
* Removed NewPath function
* Removed Reset methods from Path interface
# v0.16.0
* Can use ListAdapter as "content" property value of ListLayout

View File

@ -4443,7 +4443,17 @@ rotation - угол поворота эллипса относительно ц
#### Path
Интерфейс Path позволяет описать сложную фигуру. Создается Path с помощью функции NewPath().
Интерфейс Path позволяет описать сложную фигуру. Для создания объекта Path используются два метода Canvas:
NewPath() Path
NewPathFromSvg(data string) Path
Метод NewPath() создает пустую фигуру. Далее вы должны описать фигуру используя методы интерфейса Path
Метод NewPathFromSvg(data string) Path создает фигуру описанную в параметре data.
Параметр data является описанием фигуры в формате елемента <path> svg изображения. Например
path := canvas.NewPathFromSvg("m 305,77.362183 c 0,0 -3,8.648649 -13,21.621616 -10,12.972981 -17,18.378381 -17,18.378381 0,0 6,4.32433 17,18.37838 11,14.05406 13,21.62162 13,21.62162 0,0 7.83867,-14.92584 13,-21.62162 10,-12.97297 17,-18.37838 17,-18.37838 0,0 -7,-5.4054 -17,-18.378381 C 308,86.010832 305,77.362183 305,77.362183 Z")
После создания вы должны описать фигуру. Для этого могут использоваться следующие функции интерфейса:

View File

@ -4411,7 +4411,17 @@ rotation - the angle of rotation of the ellipse relative to the center in radian
#### Path
The Path interface allows you to describe a complex shape. Path is created using the NewPath () function.
The Path interface allows you to describe a complex shape. Two Canvas methods are used to create a Path object:
NewPath() Path
NewPathFromSvg(data string) Path
The NewPath() method creates an empty shape. Next, you must describe the shape using the methods of the Path interface
The NewPathFromSvg(data string) Path method creates the shape described in the data parameter.
The data parameter is a description of the shape in the format of a <path> svg image element. For example
path := canvas.NewPathFromSvg("m 305,77.362183 c 0,0 -3,8.648649 -13,21.621616 -10,12.972981 -17,18.378381 -17,18.378381 0,0 6,4.32433 17,18.37838 11,14.05406 13,21.62162 13,21.62162 0,0 7.83867,-14.92584 13,-21.62162 10,-12.97297 17,-18.37838 17,-18.37838 0,0 -7,-5.4054 -17,-18.378381 C 308,86.010832 305,77.362183 305,77.362183 Z")
Once created, you must describe the shape. For this, the following interface functions can be used:

View File

@ -2136,3 +2136,11 @@ function setCssVar(tag, value) {
root.style.setProperty(tag, value);
}
}
function createPath2D(svg) {
if (svg) {
return new Path2D(svg);
} else {
return new Path2D();
}
}

View File

@ -263,6 +263,11 @@ type Canvas interface {
// and is stroked (outlined) according to the current strokeStyle and other context settings
FillAndStrokeEllipse(x, y, radiusX, radiusY, rotation float64)
// NewPath creates a new Path object
NewPath() Path
// NewPathFromSvg creates a new Path and initialize it by a string consisting of SVG path data
NewPathFromSvg(data string) Path
// FillPath draws a path that is filled according to the current FillStyle.
FillPath(path Path)
// StrokePath draws a path that is stroked (outlined) according to the current strokeStyle
@ -346,8 +351,7 @@ func (canvas *canvasData) ClipRect(x, y, width, height float64) {
}
func (canvas *canvasData) ClipPath(path Path) {
path.create(canvas.session)
canvas.session.callCanvasFunc("clip")
canvas.session.callCanvasFunc("clip", path.obj())
}
func (canvas *canvasData) SetScale(x, y float64) {
@ -779,19 +783,16 @@ func (canvas *canvasData) StrokeText(x, y float64, text string) {
}
func (canvas *canvasData) FillPath(path Path) {
path.create(canvas.session)
canvas.session.callCanvasFunc("fill")
canvas.session.callCanvasFunc("fill", path.obj())
}
func (canvas *canvasData) StrokePath(path Path) {
path.create(canvas.session)
canvas.session.callCanvasFunc("stroke")
canvas.session.callCanvasFunc("stroke", path.obj())
}
func (canvas *canvasData) FillAndStrokePath(path Path) {
path.create(canvas.session)
canvas.session.callCanvasFunc("fill")
canvas.session.callCanvasFunc("stroke")
canvas.session.callCanvasFunc("fill", path.obj())
canvas.session.callCanvasFunc("stroke", path.obj())
}
func (canvas *canvasData) DrawLine(x0, y0, x1, y1 float64) {

View File

@ -134,7 +134,7 @@ func (object *dataObject) PropertyObject(tag string) DataObject {
}
func (object *dataObject) setNode(node DataNode) {
if object.property == nil || len(object.property) == 0 {
if len(object.property) == 0 {
object.property = []DataNode{node}
} else {
tag := node.Tag()

View File

@ -1,3 +1,5 @@
//go:build !wasm
package rui
import (
@ -39,6 +41,7 @@ Example for echo:
}
})
*/
func NewHandler(urlPrefix string, createContentFunc func(Session) SessionContent, params AppParams) *httpHandler {
app := new(application)
app.params = params

54
path.go
View File

@ -2,9 +2,6 @@ package rui
// Path is a path interface
type Path interface {
// Reset erases the Path
Reset()
// MoveTo begins a new sub-path at the point specified by the given (x, y) coordinates
MoveTo(x, y float64)
@ -58,79 +55,76 @@ type Path interface {
// If the shape has already been closed or has only one point, this function does nothing.
Close()
create(session Session)
}
type pathElement struct {
funcName string
args []any
//create(session Session)
obj() any
}
type pathData struct {
elements []pathElement
session Session
varName any
}
// NewPath creates a new empty Path
func NewPath() Path {
func (canvas *canvasData) NewPath() Path {
path := new(pathData)
path.Reset()
path.session = canvas.session
path.varName = canvas.session.createPath("")
return path
}
func (path *pathData) Reset() {
path.elements = []pathElement{
{funcName: "beginPath", args: []any{}},
}
func (canvas *canvasData) NewPathFromSvg(data string) Path {
path := new(pathData)
path.session = canvas.session
path.varName = canvas.session.createPath(data)
return path
}
func (path *pathData) MoveTo(x, y float64) {
path.elements = append(path.elements, pathElement{funcName: "moveTo", args: []any{x, y}})
path.session.callCanvasVarFunc(path.varName, "moveTo", x, y)
}
func (path *pathData) LineTo(x, y float64) {
path.elements = append(path.elements, pathElement{funcName: "lineTo", args: []any{x, y}})
path.session.callCanvasVarFunc(path.varName, "lineTo", x, y)
}
func (path *pathData) ArcTo(x0, y0, x1, y1, radius float64) {
if radius > 0 {
path.elements = append(path.elements, pathElement{funcName: "arcTo", args: []any{x0, y0, x1, y1, radius}})
path.session.callCanvasVarFunc(path.varName, "arcTo", x0, y0, x1, y1, radius)
}
}
func (path *pathData) Arc(x, y, radius, startAngle, endAngle float64, clockwise bool) {
if radius > 0 {
if !clockwise {
path.elements = append(path.elements, pathElement{funcName: "arc", args: []any{x, y, radius, startAngle, endAngle, true}})
path.session.callCanvasVarFunc(path.varName, "arc", x, y, radius, startAngle, endAngle, true)
} else {
path.elements = append(path.elements, pathElement{funcName: "arc", args: []any{x, y, radius, startAngle, endAngle}})
path.session.callCanvasVarFunc(path.varName, "arc", x, y, radius, startAngle, endAngle)
}
}
}
func (path *pathData) BezierCurveTo(cp0x, cp0y, cp1x, cp1y, x, y float64) {
path.elements = append(path.elements, pathElement{funcName: "bezierCurveTo", args: []any{cp0x, cp0y, cp1x, cp1y, x, y}})
path.session.callCanvasVarFunc(path.varName, "bezierCurveTo", cp0x, cp0y, cp1x, cp1y, x, y)
}
func (path *pathData) QuadraticCurveTo(cpx, cpy, x, y float64) {
path.elements = append(path.elements, pathElement{funcName: "quadraticCurveTo", args: []any{cpx, cpy, x, y}})
path.session.callCanvasVarFunc(path.varName, "quadraticCurveTo", cpx, cpy, x, y)
}
func (path *pathData) Ellipse(x, y, radiusX, radiusY, rotation, startAngle, endAngle float64, clockwise bool) {
if radiusX > 0 && radiusY > 0 {
if !clockwise {
path.elements = append(path.elements, pathElement{funcName: "ellipse", args: []any{x, y, radiusX, radiusY, rotation, startAngle, endAngle, true}})
path.session.callCanvasVarFunc(path.varName, "ellipse", x, y, radiusX, radiusY, rotation, startAngle, endAngle, true)
} else {
path.elements = append(path.elements, pathElement{funcName: "ellipse", args: []any{x, y, radiusX, radiusY, rotation, startAngle, endAngle}})
path.session.callCanvasVarFunc(path.varName, "ellipse", x, y, radiusX, radiusY, rotation, startAngle, endAngle)
}
}
}
func (path *pathData) Close() {
path.elements = append(path.elements, pathElement{funcName: "close", args: []any{}})
path.session.callCanvasVarFunc(path.varName, "close")
}
func (path *pathData) create(session Session) {
for _, element := range path.elements {
session.callCanvasFunc(element.funcName, element.args...)
}
func (path *pathData) obj() any {
return path.varName
}

View File

@ -683,7 +683,7 @@ func (manager *popupManager) showPopup(popup Popup) {
}
session := popup.Session()
if manager.popups == nil || len(manager.popups) == 0 {
if len(manager.popups) == 0 {
manager.popups = []Popup{popup}
} else {
manager.popups = append(manager.popups, popup)

View File

@ -24,6 +24,7 @@ type bridge interface {
callCanvasVarFunc(v any, funcName string, args ...any)
callCanvasImageFunc(url string, property string, funcName string, args ...any)
createCanvasVar(funcName string, args ...any) any
createPath2D(arg string) any
updateCanvasProperty(property string, value any)
canvasFinish()
canvasTextMetrics(htmlID, font, text string) TextMetrics
@ -151,6 +152,7 @@ type Session interface {
canvasStart(htmlID string) bool
callCanvasFunc(funcName string, args ...any)
createCanvasVar(funcName string, args ...any) any
createPath(arg string) any
callCanvasVarFunc(v any, funcName string, args ...any)
callCanvasImageFunc(url string, property string, funcName string, args ...any)
updateCanvasProperty(property string, value any)
@ -561,6 +563,13 @@ func (session *sessionData) createCanvasVar(funcName string, args ...any) any {
return nil
}
func (session *sessionData) createPath(arg string) any {
if session.bridge != nil {
return session.bridge.createPath2D(arg)
}
return nil
}
func (session *sessionData) callCanvasVarFunc(v any, funcName string, args ...any) {
if session.bridge != nil && v != nil {
session.bridge.callCanvasVarFunc(v, funcName, args...)

View File

@ -313,7 +313,7 @@ func (session *sessionData) Language() string {
return session.language
}
if session.languages != nil && len(session.languages) > 0 {
if len(session.languages) > 0 {
return session.languages[0]
}

View File

@ -454,11 +454,7 @@ func (clip *polygonClip) cssStyle(session Session) string {
}
func (clip *polygonClip) valid(session Session) bool {
if clip.points == nil || len(clip.points) == 0 {
return false
}
return true
return len(clip.points) > 0
}
func parseClipShape(obj DataObject) ClipShape {

View File

@ -66,7 +66,7 @@ func (container *viewsContainerData) Append(view View) {
if view != nil {
htmlID := container.htmlID()
view.setParentID(htmlID)
if container.views == nil || len(container.views) == 0 {
if len(container.views) == 0 {
container.views = []View{view}
} else {
container.views = append(container.views, view)

View File

@ -193,6 +193,17 @@ func (bridge *wasmBridge) createCanvasVar(funcName string, args ...any) any {
return result
}
func (bridge *wasmBridge) createPath2D(arg string) any {
if arg != "" {
result := bridge.canvas.Call("createPath2D", arg)
bridge.printFuncToLog("var "+result.String()+" = new Path2D", arg)
return result
}
result := bridge.canvas.Call("createPath2D")
bridge.printFuncToLog("var " + result.String() + " = new Path2D")
return result
}
func (bridge *wasmBridge) updateCanvasProperty(property string, value any) {
if !bridge.canvas.IsNull() {
if ProtocolInDebugLog {

View File

@ -350,6 +350,20 @@ func (bridge *webBridge) createCanvasVar(funcName string, args ...any) any {
return result
}
func (bridge *webBridge) createPath2D(arg string) any {
bridge.canvasVarNumber++
result := canvasVar{name: fmt.Sprintf("v%d", bridge.canvasVarNumber)}
bridge.canvasBuffer.WriteString("\nlet ")
bridge.canvasBuffer.WriteString(result.name)
bridge.canvasBuffer.WriteString(` = new Path2D(`)
if arg != "" {
argText, _ := bridge.argToString(arg)
bridge.canvasBuffer.WriteString(argText)
}
bridge.canvasBuffer.WriteString(`);`)
return result
}
func (bridge *webBridge) callCanvasVarFunc(v any, funcName string, args ...any) {
varName, ok := v.(canvasVar)
if !ok {