Raphael JS: Changing circle into a another shape using a path - javascript

I currently have created a ball bouncing
var ball = paper.circle(700,275,25,25)
var a = 50;
ball.attr({
fill: "180-black-red"
});
In this function the ball bounces to the top. I then tried to make it change shape by doing ball.animate and the path. But this is not working.
function bounce_normal(){
ball.animate({cy: 220, cx: 275}, 500, 'ease-out' );
ball.animate({ path: "M190.5,320.5A20,20,0,1,1,190.1,320.5Z"});
}
I also tried to remove the cy and cx values however it still doesn't change shape. Is there a way to solve this?
Update
I now learnt I need to use a path for by ball.
var ball = paper.path("M190.5,320.5A20,20,0,1,1,190.1,320.5Z")
var a = 50;
ball.attr({
fill: "180-black-red"
});
Is there anyway of learning what that path means so i can animate the pathm ie: making it bounce ?

Related

PIXI JS - I want to change Width/height and Position of Rectangle with Mouse

var rectangle = new Graphics();
rectangle.beginFill(0, 0.001);
rectangle.lineStyle(1, 0xFF0000);
rectangle.drawRect(5, 5, 200, 100);
rectangle.interactive = true;
rectangle.buttonMode = true;
rectangle.on('pointerdown', onDragStart)
.on('pointerup', onDragEnd)
.on('pointerupoutside', onDragEnd)
.on('pointermove', onDragMove);
app.viewport.addChild(rectangle);
I'm using this code to create a rectangle and adding it to rectangle. This is the onDragMove Function
function onDragMove() {
if (this.dragging) {
const newPosition = this.data.getLocalPosition(this.parent);
this.width = newPosition.x;
this.height = newPosition.y;
}
}
This is basically changing its width and height, but I also want to Drag the Rectangle when clicked inside the rectangle and dragged on the screen. Any suggestions how can I achieve this?
Borders to change width/height
clicking inside rectangle to drag on the screen.
I created working example of dragging and resizing: https://www.pixiplayground.com/#/edit/SbpTjm7WKXbL51kmiG89W - please check.
when you click near bottom border of rectangle (+/- 20 px) then you will start resizing it.
when you click in any other place inside rectangle then you will drag it
Basing on this example i think you can implement resizing of other borders of rectangle etc :)
One note: please look at function drawRectangle :
function drawRectangle(rectangle)
{
rectangle.clear();
rectangle.beginFill(0, 0.001);
rectangle.lineStyle(1, 0xFF0000);
rectangle.drawRect(rectangle.myRectanglePosition[0], rectangle.myRectanglePosition[1], rectangle.myRectanglePosition[2], rectangle.myRectanglePosition[3]);
}
^ the rectangle.clear(); is called to redraw the PIXI.Graphics object. So on each frame we clear and draw it again on specific position with specific width & height.

Position mouse pointer on line/path in Raphael

In this jsFiddle I have a Raphael canvas with a line/path where the user can drag it.
Problem is that the exact top pixel of the mouse pointer has to be on the line to be able to drag it. I need Raphael to be more "forgiving" and let the user drag the line if it touches the top, say, 3 pixels of the pointer.
I added mouseover/mouseout events to actually tell when the mouse is over the line, otherwise is very difficult to know.
So the question is: is there a way to drag the line without having to accurately position the mouse pointer?
var paper = Raphael("canvas", 600, 600);
var line = this.paper.path('M10 10 L50 50');
var start = function () {
this.odx = 0;
this.ody = 0;
},
move = function (dx, dy) {
this.translate(dx - this.odx, dy - this.ody);
this.odx = dx;
this.ody = dy;
},
up = function () {};
line.drag(move, start, up);
line.mouseover(function(e) {
line.attr('stroke', 'red');
});
line.mouseout(function(e) {
line.attr('stroke', 'black');
});
The Raphael library creates an SVG element (not a CANVAS element) for drawing purposes, and drawing lines creates PATH elements within the SVG element.
I had some success by increasing the line width on hover. You do have to trigger the width change by at least moving the mouse over the line, but it is a lot easier to select afterwards. While the visual effect produced may not be perfect (some width flicking can occur) continuing the drag operation proceeds without problem.
You could try increasing the line width by either modifying the stroke-width attribute in the mouseover and mouseout handlers:
line.mouseover(function(e) {
line.attr('stroke', 'red');
line.attr('stroke-width', '9')
});
line.mouseout(function(e) {
line.attr('stroke', 'black');
line.attr('stroke-width', '1')
});
or by modifying the stroke-width styling when hovering over all path elements in CSS using
path:hover {
stroke-width: 9;
}
According to this question Raphael does not provide an abstraction of all possible CSS styling so it could use VML in XML documents. If you can live without IE 9 support and expect users to have a modern browser you may be interested in the following snippet which
increases the width of a line on mouseover by setting class name draggable, which sets a move cursor,
when a move is started replaces draggable with dragging ( which removes the width increase) and sets a move cursor over the svg container,
removes class draggable, but not dragging, on mouseout
cleans up classes and the cursor in the up function.
"use strict";
var container = document.getElementById("canvas");
var paper = Raphael("canvas", 600, 600);
var line = this.paper.path('M10 10 L50 50');
var start = function () {
this.odx = 0;
this.ody = 0;
},
move = function (dx, dy) {
this.translate(dx - this.odx, dy - this.ody);
this.odx = dx;
this.ody = dy;
if( this.node.classList.contains("draggable")) {
this.node.classList.replace("draggable", "dragging");
container.classList.add("moveCursor");
}
},
up = function (e) {
line.node.classList.remove("draggable", "dragging");
container.classList.remove("moveCursor");
};
line.drag(move, start, up);
line.mouseover(function(e) {
if(!e.target.classList.contains("dragging")) {
e.target.setAttribute("class", "draggable");
}
});
.draggable:hover {
stroke-width: 9;
stroke:red;
cursor: move;
}
path.dragging {
stroke: red;
}
.moveCursor{
cursor:move;
}
svg {
border: thin solid blue;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/raphael/2.1.0/raphael-min.js"></script>
<!-- body-html -->
<div id="canvas"></div>
The code is basically for demonstration - if you drag a line outside the SVG element you can't see it or grab it to drag back.
Some CSS rules (i.e. path.dragging) needed additional specificity to take priority over the defaults supplied by Raphael.

Raphael.js centered text on path

What I have:
Text along a path made out of circle. It uses Raphael.js and a function called textOnPath (found here: Raphael JS Text Along path ):
var pathTest = r.path(getCircletoPath(286, 322, radius)).attr({stroke:"#b9b9b9"});
textOnPath(message, pathTest, fontSize, fontSpacing, kerning, kerning, point, textFill, fontNormal, fontFamily);
JSFiddle: http://jsfiddle.net/zorza/62hDH/1/
What I need:
The text to be centered on top of the circle.
My approach:
Try to calculate where the text should start depending on the arc size and text width. I tried to calculate the text width by creating it's invisible clone with text() function and get it's BBox width.
It doesn't quite work and the results vary depending on the web browser, font used and number of letters and spaces:
var length = r.text(100,400,message)
.attr({"font-size":fontSize,'opacity': 0, 'font-family': fontFamily})
.getBBox()
.width;
var point = (Math.PI*radius - length*fontSpacing)/2;
JSFiddle: http://jsfiddle.net/zorza/k8vBy/3/
Could anyone point me in the right direction?
The easiest way, IMHO, is to create additional helper path that is raised by half of text size. http://jsfiddle.net/p84VQ/
Also, I find it a bit more convenient to define a circle and then get points at specified angle:
var Circle = function(cx, cy, r) {
return function (a) {
return {
x: cx + r*Math.sin(Math.PI*-a/180),
y: cy - r*Math.cos(Math.PI*-a/180)
}
}
};

How to add outline to the active text in Fabric.js

I have used canvas in the html5 using fabric js .
I want to apply outlines to the active text on the canvas. following code I have written it is working fine but problem is when I increase the thickness of outline then it overlaps on the text that means text color disappears.
activeObject1.stroke = color;
activeObject1.strokeWidth = 5;
and one more thing by applying this I am unable to apply 2nd outline.
I got one example but it is not working with the fabricjs.
http://jsfiddle.net/vNWn6/
Fabric.js first applies a fill, followed by the stroke. You will need to invert the order in order to achieve the results.
original
_renderText: function(ctx) {
this._renderTextFill(ctx);
this._renderTextStroke(ctx);
}
Before
modified
_renderText: function(ctx) {
this._renderTextStroke(ctx);
this._renderTextFill(ctx);
}
After
version: fabric-1-7-1.js
fabric.Text.prototype.set({
fill: '#000',
stroke: '#fff',
strokeWidth: 4,
paintFirst: 'stroke', // stroke behind fill
})
since 2017-09-17
var active_obj = canvas.getActiveObject();
active_obj.stroke = '#000';
active_obj.strokeWidth = 5;
canvas.renderAll();

How to prevent loss hover in Raphael?

I'm developing some page when I use Raphael liblary to draw some items.
my App
So my problem is in that when I'm moving to some rect it growing up but when my mouse is on text which is positioning on my rect, it loss his hover. You can see it on my app example.
var paper = new Raphael(document.getElementById('holder'), 500, object.length * 100);
drawLine(paper, aType.length, bType.length, cType.length, cellSize, padding);
process = function(i,label)
{
txt = paper.text(390,((i+1)* cellSize) - 10,label.devRepo)
.attr({ stroke: "none", opacity: 0, "font-size": 20});
var a = paper.rect(200, ((i+1)* cellSize) - 25, rectWidth, rectHeight)
.hover(function()
{
this.animate({ transform : "s2"}, 1000, "elastic");
this.prev.animate({opacity: 1}, 500, "elastic");
this.next.attr({"font-size" : 30});
},
function()
{
this.animate({ transform : "s1" }, 1000, "elastic");
this.prev.animate({opacity: 0}, 500);
this.next.attr({"font-size" : 15});
});
}
I have tried e.preventDefault(); on hover of this.next and some other solutions but it's doesn't work.
Any help would be appreciated.
Most people will suggest you place a transparent rectangle over the box and the labels and attach the hover functions to that instead. (If memory serves, you have to make the opacity 0.01 instead of 0 to prevent the object from losing its attached events.) This works fine, but I don't love this solution; it feels hacky and clutters the page with unnecessary objects.
Instead, I recommend this: Remove the second function from the hover, making it functionally a mouseover function only. Before you draw any of the rectangles and labels, make a rectangular "mat" the size of the paper. Then, attach the function that minimizes the label as a mouseover on the mat. In other words, you're changing the trigger from mousing out of the box to mousing over the area outside of it.
I left a tiny bit of opacity and color on the mat to be sure it's working. You can just change the color to your background color.
var mat = paper.rect(0, 0, paper.width, paper.height).attr({fill: "#F00", opacity: 0.1});
Now, you want to make a container for all the rectangles so you can loop through them to see which need to be minimized. I made an object called "rectangles" that contains the objects we're concerned with. Then:
mat.mouseover(function () {
for (var c = 0; c < rectangles.length; c += 1) {
//some measure to tell if rectangle is presently expanded
if (rectangles[c].next.attr("font-size")) {
rectangles[c].animate({
transform : "s1"
}, 1000, "elastic");
rectangles[c].prev.animate({opacity: 0}, 500);
rectangles[c].next.attr({"font-size" : 15});
}
}
});
Then I just removed the mouseout function from the individual rectangles.
jsBin
To be clear, this will have some downsides: If people run the mouse around really fast, they can expand several rectangles at the same time. This is remedied as soon as the mouse touches the mat. I think the functionality looks pretty nice. But the invisible mats is always an option.
I wrote a small extension to Raphael - called hoverInBounds - that resolves this limitation.
Demo: http://jsfiddle.net/amustill/Bh276/1
Raphael.el.hoverInBounds = function(inFunc, outFunc) {
var inBounds = false;
// Mouseover function. Only execute if `inBounds` is false.
this.mouseover(function() {
if (!inBounds) {
inBounds = true;
inFunc.call(this);
}
});
// Mouseout function
this.mouseout(function(e) {
var x = e.offsetX || e.clientX,
y = e.offsetY || e.clientY;
// Return `false` if we're still inside the element's bounds
if (this.isPointInside(x, y)) return false;
inBounds = false;
outFunc.call(this);
});
return this;
}

Categories