简体   繁体   English

KonvaJS 在 SVG 上围绕中心变换旋转

[英]KonvaJS transform rotation around center on SVG

I create text on canvas using KonvaJS .我使用KonvaJS在 canvas 上创建文本。 And I can freeze the text using Transformer.我可以使用 Transformer 冻结文本。 While drawing, the origin remains in the center as I wish there is no problem here.在绘图时,原点仍然在中心,因为我希望这里没有问题。 However, when I want to use the data with svg here, x and y come true without freezing.但是,当我想在这里使用 svg 的数据时, xy会在没有冻结的情况下实现。 But when I do ice cream it freezes outside the center.但是当我做冰淇淋时,它会在中心外结冰。 Here这里

transform={{
    rotation: 90,
    originX: x + width / 2,
    originY: y + height / 2,
}}

It works when I freeze using it.当我冻结使用它时它会起作用。 Because x and y values are not changing.因为 x 和 y 值没有变化。 However, while drawing on KonvJs, if I freeze, the values of xtation and y change together with the value of ratation .但是,在使用 KonvJs 时,如果我冻结, xtationy的值会与ratation的值一起改变。 The code between the shortened example.缩短示例之间的代码。

import React, { Fragment, useEffect, useRef } from 'react'
import { Text, Transformer } from 'react-konva'

import { useStore } from './store'

export default function ({ id, text }) {
  const { regions, selected, setRegions, setSelected } = useStore()

  const { x, y, value, color, rotation, fontSize } = text

  const TextRef = useRef()
  const TransformRef = useRef()

  const onDragEnd = ({ target }) => {
    setRegions(
      regions.map((item) => {
        if (item.id === id) {
          item.text = {
            ...item.text,
            x: target.x(),
            y: target.y(),
            width: target.width(),
            height: target.height(),
          }
        }

        return item
      })
    )
  }

  const onTransformEnd = () => {
    const node = TextRef.current

    const width = node.width()
    const height = node.height()

    const x = node.x()
    const y = node.y()
    const rotation = node.rotation()

    const originX = x + width / 1.3
    const originY = y + height / 1.3

    setRegions(
      regions.map((item) => {
        if (item.id === id) {
          item.text = {
            ...item.text,
            x, // <= it changes when this is rotation
            y, // <= it changes when this is rotation
            rotation,
            originX,
            originY,
          }
        }

        return item
      })
    )
  }


  const isSelected = id === selected

  useEffect(() => {
    if (isSelected) {
      TransformRef.current.setNode(TextRef.current)
      TransformRef.current.getLayer().batchDraw()
    }
  }, [isSelected])

  return (
    <Fragment>
      <Text
        draggable
        name="region"
        x={x}
        y={y}
        text={value}
        fill={color}
        ref={TextRef}
        rotation={rotation}
        fontSize={fontSize}
        onDragEnd={onDragEnd}
        onTransformEnd={onTransformEnd}
      />

      {isSelected && (
        <Transformer
          ref={TransformRef}
        />
      )}
    </Fragment>
  )
}

It will be enough to work in the section I made by giving offset in the convention.通过在约定中给出偏移量来完成我所做的部分就足够了。 The important example is that I can show with svg on the client side.重要的例子是我可以在客户端显示 svg。 React Native Svg反应原生 Svg

<G
    transform={{
        rotation: rotation,
        originX: x + width / 2,
        originY: y + height / 2,
    }}>

    <Text
        x={x}
        y={y}
        fill={'#fff'}
        fontSize={fontSize}
        textAnchor="start"
    >
        {value}
    </Text>
</G>

You may need to calculate the center of the shape, to position it in SVG correctly.您可能需要正确计算形状的中心,以 position 它在 SVG 中。

function getCenter(shape) {
  return {
    x:
      shape.x +
      (shape.width / 2) * Math.cos(shape.rotation) +
      (shape.height / 2) * Math.sin(-shape.rotation),
    y:
      shape.y +
      (shape.height / 2) * Math.cos(shape.rotation) +
      (shape.width / 2) * Math.sin(shape.rotation)
  };
}

function Show({ text, x, y, rotation, width, height }) {
  const center = getCenter({
    x,
    y,
    width,
    height,
    rotation: (rotation / 180) * Math.PI
  });

  return (
    <svg width={window.innerWidth} height={window.innerHeight / 2}>
      <text
        y={height / 1.3}
        fill="#000"
        fontSize={50}
        alignment-baseline="bottom"
        transform={`translate(${x}, ${y}) rotate(${rotation})`}
      >
        {text}
      </text>
      {/* Origin Circl  */}
      <circle cx={center.x} cy={center.y} r={10} fill="red" />
    </svg>
  );
}

Demo: https://codesandbox.io/s/konva-and-svg-demo-jx7sj?file=/src/Playground.js:1704-2583演示: https://codesandbox.io/s/konva-and-svg-demo-jx7sj?file=/src/Playground.js:1704-2583

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM