Adding a double stroke to an Image Component in React Knova is a simple process that can enhance

Below is the code for a component I am working on:

      <Image
        // stroke={perPageFrameColor?.filter((item) => item.page == pageCurrent+1)[0]?.framecolor}
        stroke={color?.framecolor}
        strokeWidth={stroke}
        onClick={onSelect}
        onTap={onSelect}
        ref={shapeRef}
        {...shapeProps}
        draggable
        onDragEnd={(e) => {
          onChange({
            ...shapeProps,
            x: e.target.x(),
            y: e.target.y(),
          });
        }}
        onTransformEnd={(e) => {
          // transformer is changing scale of the node
          // and NOT its width or height
          // but in the store we have only width and height
          // to match the data better we will reset scale on transform end
          const node = shapeRef.current;
          const scaleX = node.scaleX();
          const scaleY = node.scaleY();

          // we will reset it back
          node.scaleX(1);
          node.scaleY(1);
          setDrag({
            ...drag,
            x: node.x(),
            y: node.y(),
          });
          onChange({
            ...shapeProps,
            x: node.x(),
            y: node.y(),
            // set minimal value
            width: Math.max(5, node.width() * scaleX),
            height: Math.max(node.height() * scaleY),
          });
        }}
        image={image}
        onDragStart={() => {
          setDrag({
            isDragging: true,
          });
        }}
        shadowColor="red"
        shadowOffset={{x:20,y:20}}
      />

I am trying to add inner and outline strokes to the image component provided by React Knova.

Could someone please guide me on how to achieve this in React Knova?

I attempted to implement this by using the above shadowOffset property. However, it seems to only apply to the left and bottom sides. How can I accomplish my goal using React Knova? I have made several attempts, but haven't been successful in finding a solution.

Answer №1

If you encounter this problem, the solution lies in utilizing sceneFunction:

      <Image
      
      sceneFunc={(context, shape) => {
        const width = shapeProps.width;
        const height = shapeProps.height;
        if (
          perPageOutlineColor?.filter(
            (item) => item.page == pageCurrent + 1
          )[0]?.color
        ) {
          // Adding outer stroke
          context.beginPath();
          context.moveTo(-10, -10);
          context.lineTo(width + 10, -10);
          context.lineTo(width + 10, height + 10);
          context.lineTo(-10, height + 10);
          context.closePath();
          context.strokeStyle = perPageOutlineColor?.filter(
            (item) => item.page == pageCurrent + 1
          )[0]?.color;
          context.lineWidth = 16;
          context.stroke();
        }

        // Compute inner rectangle dimensions
        const innerWidth = width - 4 * stroke;
        const innerHeight = height - 4 * stroke;
        const innerX = 2 * stroke;
        const innerY = 2 * stroke;

        // Inner stroke
        context.beginPath();
        context.moveTo(innerX, innerY);
        context.lineTo(innerX + innerWidth, innerY);
        context.lineTo(innerX + innerWidth, innerY + innerHeight);
        context.lineTo(innerX, innerY + innerHeight);
        context.closePath();
        context.strokeStyle =  perPageOutlineColor?.filter(
          (item) => item.page == pageCurrent + 1
        )[0]?.color? "white":color?.framecolor; // Specify desired color for inner stroke
        context.lineWidth = stroke;
        context.stroke();
      
        if (perPageOutlineColor?.filter(
          (item) => item.page == pageCurrent + 1
        )[0]?.color) {
             context.fillStyle=color?.framecolor;
        context.fillRect(innerX - 2*stroke-2, innerY - 2*stroke-2, width+4, height+4)
    
        }

        // Display loaded image
        if (image) {
          context.drawImage(image, innerX, innerY, innerWidth, innerHeight);
        }

        context.fillStrokeShape(shape);
      }}
      // stroke={perPageFrameColor?.filter((item) => item.page == pageCurrent+1)[0]?.framecolor}
      // stroke={color?.framecolor}
      strokeWidth={stroke}
      onClick={onSelect}
      onTap={onSelect}
      
      ref={shapeRef}
      {...shapeProps}
      draggable
      onDragEnd={(e) => {
        onChange({
          ...shapeProps,
          x: e.target.x(),
          y: e.target.y(),
        });
      }}
      onTransformEnd={(e) => {
        // Transformer changes scale of node
        // and not its width or height
        // To better match the data, reset scale on transform end
        const node = shapeRef.current;
        const scaleX = node.scaleX();
        const scaleY = node.scaleY();

        // Reset back to default
        node.scaleX(1);
        node.scaleY(1);
        setDrag({
          ...drag,
          x: node.x(),
          y: node.y(),
        });
        onChange({
          ...shapeProps,
          x: node.x(),
          y: node.y(),
          // Ensure minimum value
          width: Math.max(5, node.width() * scaleX),
          height: Math.max(node.height() * scaleY),
        });
      }}
      image={image}
      onDragStart={() => {
        setDrag({
          isDragging: true,
        });
      }}
    />

Your approach will determine the final outcome.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Creating redux reducers that rely on the state of other reducers

Working on a dynamic React/Redux application where users can add and interact with "widgets" in a 2D space, allowing for multiple selections at once. The current state tree outline is as follows... { widgets: { widget_1: { x: 100, y: 200 }, widg ...

Encountering a CORS policy issue: The requested resource does not have the necessary 'Access-Control-Allow-Origin' header when attempting to upload a file through nodejs and react

[Placeholder for image description][1]Encountering a CORS error "No 'Access-Control-Allow-Origin'" when attempting to upload a file from ReactJS to NodeJS. Despite adding all necessary headers, the issue persists. Other requests are functioning b ...

Ways to display spinner animations during image loading on Next.js?

Currently, I am attempting to implement a spinner display while images are loading on a Next.js website. To achieve this, I am utilizing the NextUI UI library. My website features several cards, and my goal is to showcase a spinner during the image loadin ...

Implementing a color change for icons in React upon onClick event

export default function Post({post}) { const [like,setLike] = useState(post.like) const [islike,setIslike] = useState(false) const handler=()=>{ setLike(islike? like-1:like+1 ) setIslike(!islike) } return ( <> <div classNam ...

The error message displayed is: "github-pages: ENOENT: file or directory not found, attempting to access '* extuild'"

I am facing an issue while trying to deploy my Next.js project on GitHub. I followed the instructions from and installed gh-pages in my project using: npm install --save gh-pages After running the command: npm run deploy The project was successfully bui ...

Can you explain the distinction between the server component and client component in Nextjs 14?

export default function CustomLayout({ children, }: { children: React.ReactNode; }) { return ( <html lang="ko-KR"> <link rel="icon" href="/favicon.ico" sizes="any" /> <body> ...

Guide to encapsulating a container within a map function using a condition in JSX and TypeScript

Currently, I am working with an array of objects that are being processed by a .map() function. Within this process, I have a specific condition in mind - if the index of the object is greater than 1, it should be enclosed within a div element with a parti ...

What is the best way to retrieve cookies using getinitial props in Next.js?

Is there a way to retrieve cookies in getInitialProps and use them to fetch data from an API on a page in Next.js? ...

Having trouble locating the componentwillunmountafterInteraction in the React Native deck swiper

I've been utilizing react native deckSwiper in my project, but I'm having trouble unmounting it from the screen due to an error that says "ReferenceError: Can't find variable componentWillUnmountAfterInteractions". The error stack trace is s ...

Unable to upload code onto GitHub due to the excessive size of node modules

I recently restructured my react project, separating the front-end code into a client directory while keeping the back-end code in the root directory. However, I encountered an issue when trying to push my code to GitHub. An error message indicated that th ...

Issue with onExited method in material-ui component not functioning as expected

I'm attempting to implement the onExited method (Material-UI v1.0.0-beta.41) in my React.js code like this: fireOnExit=()=>{ alert("Exited"); } <button label="Cancel" onClick={this.handleClose} onExited{()=>this.fireOnExit()}/> Unfo ...

Ways to refresh the session on the server end

What is the process for updating a session in the server side using authV5 in the most recent update of nextjs? I have attempted the following: import { update } from "@/auth However, I am unable to locate the update function within the auth module ...

Utilizing AWS Amplify to access detailed owner information beyond just their ID

Is it feasible to achieve something like this? How should the design be tailored for this specific use case? Do I need to incorporate a lambda function that includes the user (owner) in the post creation process? Seeking assistance on how to implement thi ...

The request to http://localhost:3000 received a 500 Internal Server Error response in 197ms

I have implemented backend CORS middleware, but it doesn't seem to affect anything. When I try a POST request with Postman, it works fine. However, when I attempt to add a teacher through my front-end, I encounter an error. const express = require(&qu ...

Setting environment variables for React scripts can be done by leveraging the process.env object

Currently, I am in the process of developing a project that encompasses both backend and frontend components. It struck me as a great idea to have both sets of code housed within the same directory, complemented by another npm script responsible for runnin ...

Why is my React build's index.html coming up empty?

I've been working on a React app using Snowpack, and everything seems to be in order. The build process completes successfully, but when I try to open the index.html file from the build folder, the page appears blank. To temporarily resolve this issu ...

Sending a Thunk to the store using Typescript

Within my primary store.ts file, the following code is present: const store = createStore( rootReducer, composeWithDevTools(applyMiddleware(thunk)) ); store.dispatch(fetchUser()); Upon initial rendering, an action is dispatched to fetchUser in ord ...

The counterpart to Ruby's `.select{ |x| condition }` in Javascript/ React.js would be to

This javascript function in React.js utilizes a for loop to determine the opponent team: getOpponentTeam: function(playerTeamId){ var matches = this.state.matches; var player_team = this.state.player.team.name for (i in matches){ if (matches[i]. ...

What is the best way to trigger UseEffect when new data is received in a material table?

I was facing an issue with calling a function in the material table (https://github.com/mbrn/material-table) when new data is received. I attempted to solve it using the following code. useEffect(() => { console.log(ref.current.state.data); ...

When incorporating a JS React component in TypeScript, an error may occur stating that the JSX element type 'MyComponent' is not a valid constructor function for JSX elements

Currently, I am dealing with a JavaScript legacy project that utilizes the React framework. Within this project, there are React components defined which I wish to reuse in a completely different TypeScript React project. The JavaScript React component is ...