Sharp text and icons on a zooming stage
See original GitHub issueIt should be a common use case to want to have objects on a stage that only follow the translation of the parent, ignoring scale and rotation. I needed it for a stage that switches between icons and detail objects depending on zoom levels, and came up with the following code that might be of some use to the project. I’ve used it for pixel sharp text and icons and it works great.
It would be possible to disable scale and rotation separately as well, but this is a simple solution that I suppose covers the most common case.
Note that text that should rotate with the parent to get the correct translation, but ignore rotation around its own origin in order to stay horizontal and pixel sharp, can be achieved by calling
paralyzeTransformInheritance(myStagedText, false, true)
and then
myStagedText.rotation = -parent.rotation
See also this previously published request.
class ParalyzedInheritanceTransform extends PIXI.Transform {
updateTransform(parentTransform)
{
const lt = this.localTransform;
if (this._localID !== this._currentLocalID)
{
// get the matrix values of the displayobject based on its transform properties..
lt.a = this._cx * this.scale.x;
lt.b = this._sx * this.scale.x;
lt.c = this._cy * this.scale.y;
lt.d = this._sy * this.scale.y;
lt.tx = this.position.x - ((this.pivot.x * lt.a) + (this.pivot.y * lt.c));
lt.ty = this.position.y - ((this.pivot.x * lt.b) + (this.pivot.y * lt.d));
this._currentLocalID = this._localID;
// force an update..
this._parentID = -1;
}
if (this._parentID !== parentTransform._worldID)
{
// concat the parent matrix with the objects transform.
const pt = parentTransform.worldTransform;
const wt = this.worldTransform;
if(this.ignoreParentScaleAndRotation) {
wt.a = lt.a;
wt.b = lt.b;
wt.c = lt.c;
wt.d = lt.d;
wt.tx = lt.tx + pt.tx;
wt.ty = lt.ty + pt.ty;
} else {
wt.a = (lt.a * pt.a) + (lt.b * pt.c);
wt.b = (lt.a * pt.b) + (lt.b * pt.d);
wt.c = (lt.c * pt.a) + (lt.d * pt.c);
wt.d = (lt.c * pt.b) + (lt.d * pt.d);
wt.tx = (lt.tx * pt.a) + (lt.ty * pt.c) + pt.tx;
wt.ty = (lt.tx * pt.b) + (lt.ty * pt.d) + pt.ty}
if(this.truncateTranslation) {
wt.tx = Math.floor(wt.tx);
wt.ty = Math.floor(wt.ty)}
this._parentID = parentTransform._worldID;
// update the id of the transform..
this._worldID++;
}
}
}
//Modifies 'child' so that it does not care about parent scaling and rotation,
//and/or truncates the translation. An example 'child' object for this function
//is an object on some zoomable stage, such as an icon, that should not resize
//when zooming, and/or remain pixel sharp while zooming.
export function paralyzeTransformInheritance(child, ignoreParentScaleAndRotation, truncateTranslation) {
var t = child.transform;
if(!(t instanceof ParalyzedInheritanceTransform)) {
t = new ParalyzedInheritanceTransform();
t.setFromMatrix(child.transform.worldTransform);
child.transform = t}
t.ignoreParentScaleAndRotation = ignoreParentScaleAndRotation;
t.truncateTranslation = truncateTranslation;
return child}
Issue Analytics
- State:
- Created 4 years ago
- Reactions:4
- Comments:7 (1 by maintainers)
Top GitHub Comments
Been trying to understand how to use the above code but I found I had to do this to make it keep the X,Y translation of a child within it’s parent relative to the parent’s scale but without scaling the child (eg. like an icon stays in the same place on the map (not in the same place on the screen) and doesn’t get bigger when you zoom in on Google maps):
Now this works for Sprites but doesn’t work with my Text or Graphics (Line, Circle or Box objects).
I was using it by:
^ That works (the sprite’s scale is locked but it’s position moves with the parent’s scale
^ This doesn’t work(the text disappears when applying the paralyzeTransformInheritance(myText, true, true) line.
I’ve also tried looking at PIXI.TransformStatic but the documentation doesn’t really explain what that does or how to use it.
The playground link in the Wiki linked above - https://www.pixiplayground.com/#/edit/qjI_XLeNbxnRmI~2Mndwg - that doesn’t appear to have anything relevant?
Something that saved me to keep lines from scaling was @pixi/graphics-smooth which has a mode that’s equivalent to SVG’s ‘non-scaling-stroke’ attribute.
And whilst, yes, I could calculate all the translations for the text separately, there’s separate tweens on the parent and children that it’d be great if we could just apply one transform on a parent that the children’s scale isn’t affected.
@molst if I’m misunderstanding your code, it’d be great if you can provide an example? @ivanpopelyshev is there any solutions other than the code above for child Text and Graphics ignoring parent scale?
Yeah, there’s that problem 😃 OK, added it to wiki