-
-
Notifications
You must be signed in to change notification settings - Fork 3.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Shape gradients with percentage based coordination don't work correctly. #3665
Comments
Well svg gradients are different from canvas one. |
Alright, let's forget about my function, and just take a look at my fiddle, I am copying the coordinations from the fabricjs help docs and again it is not working this is from fabric docs:
Take a look at the last example here: https://github.com/kangax/fabric.js/wiki/Working-with-gradients P.S. In the docs it says shape gradients should be created using |
So the page has been updated a bit, not completely. SetGradientFill has been removed prior to 1.4.0 and changed with setGradient. i think jsdocs mention it but the page not. Need to be addressed. Other than that i see percentages produce an hard gradient, this is weird. i looked at the fiddle even before i did not notice the missing gradient because i was concentrated in the angle. I m planning a semplification of gradient because using x1,y1... is not comfortable. i would prefer to have a gradient angle option for linear gradient and default to full width/height. leaving gradient coords for who wants to make something different |
Thank you for giving it a look
Thanks anyways for always being responsive to the questions all the time. |
i want something more simple. the current one respect the svg logic, users generally want something simpler. |
I could not resolve the issue with percentage values since it is something done wrong inside fabric core, but there was a simple fix for my app, I change the angle to points function this, so now I am converting my percentage values to pixel based on the shape with/height, this works fine for me. Maybe the angle to point function would be useful for you too if you want to simplify the gradients for fabric so I share it with you too: const { width, height } = selectedObject;
var anglePI = (-parseInt(angle, 10)) * (Math.PI / 180)
var angleCoords = {
'x1': (Math.round(50 + Math.sin(anglePI) * 50) * width) / 100,
'y1': (Math.round(50 + Math.cos(anglePI) * 50) * height) / 100,
'x2': (Math.round(50 + Math.sin(anglePI + Math.PI) * 50) * width) / 100,
'y2': (Math.round(50 + Math.cos(anglePI + Math.PI) * 50) * height) / 100,
}
selectedObject.setGradient('fill', {
type: 'linear',
x1: angleCoords.x1 || 0,
y1: angleCoords.y1 || 0,
x2: angleCoords.x2 || 0,
y2: angleCoords.y2 || 0,
colorStops: shapeStops
})
canvas.renderAll() The reason I need this is that I have created a gradient color picker for react, and it has a draggable knob to set the angle, the return value of my gradient component can be used in CSS, SVG and now fabric shapes using the function above, I this comes handy to you too. |
did you spot something wrong that you can point me at? yes i need a react thing to make gradient. a screenshot is enough. |
I was planning on open sourcing it anyhow, since there are no other gradient pickers for React available on the web right now (there is one and it does not work) |
no i need a screenshot of the interface to have an idea on how to realize one for a separate project. If you opensource it give me a link! If is not opensource i do not want to see code, since my project is commercial and i do not want to mess up with wrong things. |
@Human-a would you mind sharing some more infos on your usage of gradients? I would like to have a simple gradient control for a linear gradient with a color picker for the left and right color and ideally a numberinput for the gradient "angle"... This is my code for creating the gradient so far:
|
@sandor Sure, here is how I did it (I am using ES6 syntax; if you are not familiar you can transpile it back to ES5 using babel) const { colorStops, angle } = gradient; // Getting these values from my custom gradient colorpicker
const { width, height } = shape;
const shapeColorStops = {}
// My gradient picker is giving me percentage values for the angle (0-100)
// Using the code below I transform the angle to a radial value (0-360)
var anglePI = (-parseInt(angle, 10)) * (Math.PI / 180)
var angleCoords = {
'x1': (Math.round(50 + Math.sin(anglePI) * 50) * width) / 100,
'y1': (Math.round(50 + Math.cos(anglePI) * 50) * height) / 100,
'x2': (Math.round(50 + Math.sin(anglePI + Math.PI) * 50) * width) / 100,
'y2': (Math.round(50 + Math.cos(anglePI + Math.PI) * 50) * height) / 100,
}
// Perhaps you won't need to loop through your color stops if you only have 2 values
// In my case I can have infinite number of color stops, so I have to loop through them
Object.keys(colorStops).forEach((key,i) => {
const leftPerc = (colorStops[key].leftPerc / 100) || 0;
shapeColorStops[leftPerc] = colorStops[key].color;
})
// You are already familiar with this part, you have done it in your code too
layer.setGradient('fill', {
type: 'linear',
x1: angleCoords.x1 || 0,
y1: angleCoords.y1 || 0,
x2: angleCoords.x2 || 0,
y2: angleCoords.y2 || 0,
colorStops: shapeColorStops
})
canvas.renderAll() As of the code the for custom gradient generator, I still haven't got the time to open source it. I am using a combination of react color component and a drag & drop component to be able to create infinite color stops and drag them around, using the same drag&drop lib for the angle too. The concept is very simple, you just have to work on the mechanics of it. Will open source it as soon as I can. |
@Human-a Excellent! Thank you very much! Since I have a numberinput that is dealing with values 0-360 is even more easier to implement. And yes, I have to take care only about two color-stops. I will try to make a short demo for fabricjs.com, since I am already dealing with Fabricjs v.2 beta... Thanks again! |
So much time passed, i think this is now fixed. Verified with this code with the wip build: canvas.getActiveObject()
var angle = 0;
var anglePI = (-parseInt(angle, 10)) * (Math.PI / 180)
var angleCoords = {
'x1': (Math.round(50 + Math.sin(anglePI) * 50)) / 100,
'y1': (Math.round(50 + Math.cos(anglePI) * 50)) / 100,
'x2': (Math.round(50 + Math.sin(anglePI + Math.PI) * 50)) / 100,
'y2': (Math.round(50 + Math.cos(anglePI + Math.PI) * 50)) / 100,
}
canvas.getActiveObject()
.setGradient('fill', {
type: 'linear',
gradientUnits: 'percentage',
x1: angleCoords.x1 || 0,
y1: angleCoords.y1 || 0,
x2: angleCoords.x2 || 0,
y2: angleCoords.y2 || 0,
colorStops: { 0: 'black', 1: 'yellow' }
})
canvas.renderAll() |
Is it normal? I also don't understand what this sentence (in the
What is an "object percantages"? |
Moreover, why |
setGradient is deprecated because is just a middleman between creating a gradient and assigning it to an object. to avoid unnecessary code, since the library is already big, i prefer to remove the not useful pieces. var gradient = new fabric.Gradient({ ...allTheOptionsForAGradient });
shape.set('fill', gradient); // this will also invalidate the cache and redraw at next render |
What we need is really more tutorials and examples. |
Thank you for the fast answer! It is indeed a better way to do with |
im not sure if you are making some demo or investigating the library for some application. So if you need some custom action from the corners, or more corners, refrain from writing crazy overrides today because they won't work with version 4. |
I am currently building a website with a simple image editor inside. This is great news a version 4 is coming! And thank you for alerting me :) |
Hi @asturur The above angle logic doesn't work well with stroke. At first, it applies correctly on the object but after scaling up the stroke disappears Note: It is working fine with Image object. But not working with Shapes (Rect, Circle, Triangle, etc..) I am using the latest release V3.6.1 |
There is definitely something wrong with my stroke logic. |
Version
1.7.3
Test Case
https://jsfiddle.net/human_a/9xfa5u77/
Steps to reproduce
In my app, I am using the following function to turn angle (degrees based) to X and Y coordinations, but even using the examples from this page would not work if I hard code them.
This function works perfectly fine and I am using the same technique to create SVG gradients for canvas background, while it works for the canvas background flawlessly, it does not work for shapes unless I use shape width and height which will limit my app for using different angles (I have a knob using which I can change the angle on mouse drag)
Expected Behavior
Percentage based coordinations should work the same as width and height based coords, but it does not produce correct gradients for shapes.
The text was updated successfully, but these errors were encountered: