Giter Club home page Giter Club logo

Comments (9)

lavrton avatar lavrton commented on May 14, 2024 1

@blueberryfan Something like this:

class MyText extends React.Component {
  componentDidMount() {
    // do your text calculations here
    const width = this.textNode.getTextWidth();
  }
  render() {
    return (
      <Text
        {...someProps}
        ref={node => {
          this.textNode = node;
        }}
      />
    );
  }
}

from react-konva.

lavrton avatar lavrton commented on May 14, 2024

You can use Konva.Label for such case http://konvajs.github.io/docs/shapes/Label.html.
Or you can use width() and height() of Konva.Text instance:

const rect = new Konva.Rect({
  x: text.x(),
  y: text.y(),
  width: text.width(),
  height: text.height(),
  fill: 'yellow'
});

http://jsbin.com/wivakif/edit?html,js,output

from react-konva.

blueberryfan avatar blueberryfan commented on May 14, 2024

What's the recommended way of doing this in React (react-konva) though, like the OP asked? Render, somehow obtain text measurements, then force a re-render?

Also see issue 130.

from react-konva.

blueberryfan avatar blueberryfan commented on May 14, 2024

Thanks for the prompt response, @lavrton. I only just started to use React and your react-konva extension, and I like it. Good work!

The main thing I was wondering about is whether, as mentioned by @arbesfeld, it's not possible to get the width and use it to position some other component in a single render.

In your last example, am I right in thinking that once the width is obtained, I'd need to trigger a second rendering in which I could then use the width?

In my case, I have a Text and I'm drawing a Line after it, but I need to know the width of the text so that I can calculate the x-value for the Line. Basically, the width of the text varies, and therefore the x-value for the Line needs to be calculated dynamically, based on the width of the Text.

I'm thinking that in componentDidMount() I could grab the width of the Text, call setState() to store the width, and upon re-render use the state to re-position the Line. This would always require two renderings though, but maybe there's no way around it?

from react-konva.

lavrton avatar lavrton commented on May 14, 2024

@blueberryfan I don't know any good ways around. As I know this is a very popular practice in React apps.

Probably you can precalculate width somehow in componentWillMount with native canvas access, but I don't think it will give real benefits.

from react-konva.

blueberryfan avatar blueberryfan commented on May 14, 2024

Ok, great. Thanks for your input. I'll have a play and post back if I find a way of not having to re-render.
Cheers!

from react-konva.

blueberryfan avatar blueberryfan commented on May 14, 2024

I ended up doing what I described above, ie a double render, which makes sense.

from react-konva.

SyntaxRules avatar SyntaxRules commented on May 14, 2024

Update: The following commit exposed measureText(): konvajs/konva@18cce13

Now you can measure the text before creating the rect with konvaLayer.getContext().measureText("some text").width.

from react-konva.

damiangreen avatar damiangreen commented on May 14, 2024

@SyntaxRules the result of measureText appears to be less than the width of textRef.current.width() for some reason. I seem to have to hack a work around by adding additional pixels. It appears this is because measureText omits any padding applied. Is this a bug?
Some example working code for those that arrive here.

const textPadding = 4

const TopologyNodeLabel = ({
  text,
  position: { x, y },
  included,
  nodeIsHovered,
}: Props) => {
  const { isDarkTheme, orientation } = useTopologyChartContextValue()
  const labelRef = useRef<Konva.Label>(null)
  const textRef = useRef<Konva.Text>(null)
  const textColor = isDarkTheme ? 'white' : 'black'
  const opacity = included || nodeIsHovered ? 1 : 0.5

  useEffect(() => {
    if (labelRef?.current && textRef?.current) {
      const width = textRef.current.measureSize(text).width + textPadding * 2
      const maxWidth =
        orientation === 'vertical'
          ? nodeLabelWidthVerticalOrientation
          : nodeLabelWidth

      const exceeds = width > maxWidth
      const newWidth = exceeds ? maxWidth : width

      textRef.current.setAttrs({
        ellipsis: exceeds,
        width: newWidth,
      } as Konva.TextConfig)

      if (orientation === 'vertical') {
        const newX = x - newWidth / 2
        labelRef.current.setAttrs({
          x: newX,
        })
      }
    }
  }, [orientation, x, text])

  const labelPosition =
    orientation === 'horizontal'
      ? { x: x + nodeLabelNodeOffset, y: y - 10 }
      : { x: x - nodeLabelWidth / 2, y: y + nodeLabelNodeOffset }
  return (
    <Label
      ref={labelRef}
      x={labelPosition.x}
      y={labelPosition.y}
      transformsEnabled="position"
      listening={false}
    >
      <Tag
        fill={isDarkTheme ? colors.midnight90 : colors.midnight10}
        opacity={opacity}
        listening={false}
        transformsEnabled="position"
      />
      <Text
        ref={textRef}
        text={text}
        padding={textPadding}
        fontFamily={fonts.dattoDIN}
        fill={textColor}
        opacity={opacity}
        wrap="none"
        listening={false}
        transformsEnabled="position"
      />
    </Label>
  )
}

export default TopologyNodeLabel

from react-konva.

Related Issues (20)

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.