Eugenius

Change the style of line that is already drawn?

Recommended Posts

Hi guys

 

It's been a long time since working with Pixi.js. Since the version 1.6 is 'in da house' with the ability to fill up complex polygons, I resumed my project again.

 

As the title says, I draw thousands of lines on WebGL using Pixi.js Graphics class. Then I change the style of the lines.

 

For example, say I drew 1000 lines on the screen, then I want to update their styles (width, color and etc) somehow not by drawing them again.

 

Is there a way to achieve this? (possibly for polygons as well?)

Share this post


Link to post
Share on other sites

You could access the graphicsData property of your graphic.
 

The data it holds are all paths defined as:
{lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, fillColor:this.fillColor, fillAlpha:this.fillAlpha, fill:this.filling, points:[], type:PIXI.Graphics.POLY}
 

However pixi will always redraw the whole graphic (all 1000 lines) whenever you call the render function unless you have cached your graphic as a bitmap.

It's probably much easier to just discard the old graphics object and create a new one when you are changing something instead of fiddling around with the pathdata.

Share this post


Link to post
Share on other sites

Thanks Sebastian, I tried the way you suggested. However the graphicsData object doesn't seem to be associated with rendering but only bounds. 

 

Actually, I draw around 20000 vertices and draw (create) them all again and style needs to change, which means I have to do all the unnecessary moveto and lineto again. Would there a be a way to manipulate the graphicsData then draw from the array?

Share this post


Link to post
Share on other sites

Explored a little more and found Graphics.dirty and Graphics.clearDirty flags needs to be set true to update from graphicsData.

 

Here's my code

 

PIXI.Graphics.prototype.updateLineStyle = function(lineWidth, color, alpha){    // console.log('lineUpdate');    var len = this.graphicsData.length;    for (var i = 0; i < len; i++) {        var data = this.graphicsData[i];        if (data.lineWidth && lineWidth) {            data.lineWidth = lineWidth;        }        if (data.lineColor && color) {            data.lineColor = color;        }        if (data.alpha && alpha) {            data.alpha = alpha;        }        this.dirty = true;        this.clearDirty = true;    }    // return this;};

Thanks again Sebastian :)

Share this post


Link to post
Share on other sites

In case anyone is trying this in PIXI v4 things are a bit different. dirty and clearDirty are now numbers not booleans, so you have to increment them. Here is a little function you can use to change any of the props for a given graphic.

function updateGraphicProps(graphic, props) {
  const graphicsData = graphic.graphicsData;
  const keys = Object.keys(props);
  const jlen = keys.length;
  let i;
  let j;
  let ilen;
  let key;
  let shape;
  // Update the props on the graphic.
  for (j = 0; j < jlen; j++) {
    key = keys[j];
    graphic[key] = props[key];
  }
  // Update the props for each shape.
  for (i = 0, ilen = graphicsData.length; i < ilen; i++) {
    shape = graphicsData[i];
    for (j = 0; j < jlen; j++) {
      key = keys[j];
      shape[key] = props[key];
    }
  }
  graphic.dirty++;
  graphic.clearDirty++;
}

Here it is in action:

 

Share this post


Link to post
Share on other sites

graphicsData seems to be moved under Graphics.geometry.graphicsData but the graphic.dirty++;  graphic.clearDirty++; seems to be having no effect in Pixi 5

This is very important and has been reported several times, but no answer so far.

Share this post


Link to post
Share on other sites

Im looking at all threads in this subforum and in pixijs github issues (https://github.com/pixijs/pixi.js/issues). I dont remember who's actually answers pixi questions in stackpverflow. Single post can be missed of course :(

As for the issue, I'm sure that there was no major requests. Usually features are implemented either by need of someone in pixijs team, or by community if people complain enough.

In that case, I tell how to achieve that theoretically and if the person does it and shares, I put it in wiki:

https://github.com/pixijs/pixi.js/wiki/v5-Migration-Guide

https://github.com/pixijs/pixi.js/wiki/v4-Resources

I know that some people used dynamic changing of colors/textures in v4, but so far no one used it in v5 due to different approach on "graphics.geometry.updateBatches" method. which produces data TWO ways: "batched" and "single drawcall".

I believe it is possible, but the estimation is like 30 minutes for me, and two hours for people who first look into that code, and for such questions I usually ask "Why do you need that?", because there can be a simpler existing way :)

Share this post


Link to post
Share on other sites
16 hours ago, ivan.popelyshev said:

Why do you need that?

I am creating a graphic design app with pixijs, migrating my existing app from Fabricjs.

I need this feature so that 1) Users can easily edit shapes, 2) When I change width and height in pixijs it is scaling the shapes, and I need to change the border thickness to match the new scale (scale.x * lineStyle.width or something like that)

You can see a live example of this in mirro.com (former realtimeboard.com) which I believe are using pixijs (look at the source code, the canvas is wrapped in a div named pixiContainer) and perhaps they are still using V4 

Lack of this feature will force me to either use V4 or give up on pixijs (which is a shame because it is awesome)

Share this post


Link to post
Share on other sites

Its easier to clear() and refill the shape. I remind you that both Flash and Canvas2D dont have API to edit paths, why shoould pixijs make a feature specifically for your type of apps? Even vector backend in chromium, skia, doesnt allow to do that.

Its hard and Its paperjs territoty. You just want renderer to somehow embed a vector editor capabilities. About realtimeboard - I dont remember how did they achieve that :( I know that similar project uses just SVG and re-rendered shapes into pixi texture every time it was changed.

Of course its possible but its actual work, it costs time. We even can do some of that stuff in shaders.

Lack of this feature will force me to either use V4 or give up on pixijs (which is a shame because it is awesome)

PixiJS is a webgl-oriented and those things are hard to do in webgl. Try PaperJS or p5, they are more design and vector-oriented, and its ok to use tools that are more suited for your task. If they dont have those features - you'll have to code it yourself as most of us do :) In that case, I recommend to hack PIXI Graphics or make your component by CTRL+C its sources and editing them.  (That's actually why pixijs exists - people hack it to add more features for their project)

I , again, remind you that even the most vector-y thing in web, FLASH, didnt have that feature.

Share this post


Link to post
Share on other sites
2 minutes ago, ivan.popelyshev said:

I remind you that both Flash and Canvas2D dont have API to edit paths, why shoould pixijs make a feature specifically for your type of apps?

Oh, I did not know that thanks for clarifying it, actually clearing and refilling could work for us since it's fast enough to look seamless to the user.

3 minutes ago, ivan.popelyshev said:

PixiJS is a webgl-oriented and those things are hard to do in webgl.

Shapes are just a small part of our app, we mostly deal with images, for which pixijs is the best possible solution out there, I tried almost all of them, none worked better than pixijs. I just hope the support for vectors and shapes become better for pixijs in future (I mean the things that are possible of course)

4 minutes ago, ivan.popelyshev said:

I recommend to hack PIXI Graphics or make your component by CTRL+C its sources and editing them.

I should extend the classes perhaps. I will share them if I achieved anything useful :)

 

Thanks for the help and clarifications.

Share this post


Link to post
Share on other sites

I just hope the support for vectors and shapes become better for pixijs in future (I mean the things that are possible of course)

I'm working on that on my main job for 2.5 years. And you're actually not the only one who requests that, there are several companies that come from flash and all want better shapes, but it also tied to Anti-Aliasing problem and its HUGE, its bigger than shapes editing. AwayJS have good progress in that, but they too dont have shapes editing.

As for extending - you have to extends both Graphics and GraphicsGeometry and maybe GraphicsData too but maybe its easier to just hack prototypes (Graphics.prototype.render = ... and so on)

The problem is actually that Graphics is not designed as dynamic data storage. For example, if you use any arcs or QuadraticCurves - they get converted to polygons very early, you wont have a chance to change their params! When we improve it and make paths like in skia or flash the problem will go away.

I think you can start here: https://github.com/pixijs/pixi.js/blob/dev/packages/graphics/src/GraphicsGeometry.js#L225 , you can copy clear method and make one that doesnt empty GraphicsData. That way you can call it after you change something in graphicsData. I think that's the easiest way.

Share this post


Link to post
Share on other sites
21 minutes ago, ivan.popelyshev said:

Its easier to clear() and refill the shape.

With that said, is there an easy way to clone and edit a Graphics element? For example if I have the following:

            let roundedRectangle = new PIXI.Graphics();
            roundedRectangle.lineStyle(1, 0xFF00FF, 1);
            roundedRectangle.name = 'roundedRectangle';
            roundedRectangle.selectable = true;
            roundedRectangle.angle = 0;
            roundedRectangle.drawRoundedRect(0, 0, 100, 100, 16);
            this.setPivotToCenter(roundedRectangle);
            roundedRectangle.position.set(700 + roundedRectangle.pivot.x, 500 + roundedRectangle.pivot.y);
            roundedRectangle.hitArea = roundedRectangle.getLocalBounds();
            this.viewport.addChild(roundedRectangle);

Now when I scale it, I would like to clear, refill and keep all of the styles, but I want to resize the shape and keep the lineStyle width at 1px.

I am looking for something built-in, if it does not exist, I will create my own.

Share this post


Link to post
Share on other sites

@Hooman Askari

I congratulate you, you were right!

The issue appeared in pixi-spine plugin https://github.com/pixijs/pixi-spine/issues/307 , and it was actually easy to fix! https://github.com/pixijs/pixi-spine/blob/master/src/Spine.ts#L14 - here is the code. I inject "invalidate" function inside GraphicsGeometry and it abuses clear(). Copy the code, call that function after you change something in "geometry.graphicsData".

I'll try to make PR in vanilla pixijs, and its probable that thing thing will appear in next minor release as official part of Graphics API.

Share this post


Link to post
Share on other sites

yeah, I even found problem in canvas implementation :)

PRhttps://github.com/pixijs/pixi.js/pull/5952

Broken: https://www.pixiplayground.com/#/edit/LP7TfzH7XSAQ3G02WZ_Mb
Fixed: https://www.pixiplayground.com/#/edit/GYy0QCPK1I62IyCxr2WH1 , it uses pixijs from a branch, look in "settings", there's a link.

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...

  • Recently Browsing   0 members

    No registered users viewing this page.