Synchronized Animation of Text and Path in Raphael JS

I've been experimenting with scaling different components of an SVG chart using Raphael js. While I have managed to scale the elements (.paths) as desired, I am now facing a challenge in scaling text alongside these scalable elements and applying .attr to the text. Is there a way to simultaneously scale a .path and .text when hovering over them? Could someone please review my jfiddle and provide some guidance on how I can achieve this? Thank you so much!!

var w = 600;
var h = 600;
var paper1 = Raphael("box");
paper1.setViewBox(0,0,w,h,false);
paper1.setSize('100%', '100%');

var ONEgrp = paper1.set();

var ONE = paper1.path("M340.1064,218.2627l97.8281-75.5117c-39.5898-48.9438-100.123-80.2485-167.9785-80.2485V186.019C298.0166,186.019,323.1533,198.5244,340.1064,218.2627z");
ONE.attr({parent: 'ONEgrp',fill: "#EFA35A",stroke:"#fff",'stroke-width':1, cursor: 'pointer'}).data('id', 'ONE');

var ONEtxt = paper1.text(340, 145, "Total Rewards\nManagement\nT1/GR1");
ONEtxt.attr('fill', '#000');
ONEtxt.attr('font-size', '12px');

ONE.mouseover(function(){
if(!ONE.data("over")) {
    ONE.attr('opacity',
    ONE.attr('opacity')*0.90); 
    ONE.toFront();
    ONE.data("over",true);
    ONEtxt.toFront();
}
});

ONE.mouseout(function(){
ONE.attr('opacity',1);
ONE.data("over",false);
ONEtxt.toFront();
});

ONEtxt.mouseover(function(){
if(!ONEtxt.data("over")) {
    ONEtxt.attr('opacity',
    ONEtxt.attr('opacity')*0.90); 
    ONEtxt.toFront();
    ONEtxt.data("over",true);
}
});
ONEtxt.mouseout(function(){
ONEtxt.toFront();
ONEtxt.attr('opacity',1);
ONEtxt.data("over",false);

});

var rsrGroups = []; 

function hovering(e){
this.animate({
    transform: 's1.2' }, 100, "elastic");
}

function hoverout(e){
this.animate({
    transform: 's1' }, 101);
}

ONE.mouseout(hoverout);
ONE.mouseover(hovering);
ONEtxt.mouseout(hoverout);
ONEtxt.mouseover(hovering);

Answer №1

To animate both elements separately, you can create a function that is called upon. Ensure to link the element and text within the function if the handler needs to be generic for various elements rather than hardcoded.

Additionally, I've included the following CSS code to prevent the text element from taking focus.

Check out the demo on jsfiddle


text {
    pointer-events: none;
}

function animateElement() {
    if(!element.data("over")) {
        element.attr('opacity', element.attr('opacity')*0.90); 
        element.toFront();
        element.data("over", true);
        text.animate({ opacity: 1 }, 100);
        text.toFront();
    }
};

function animateElementOff() {
    element.attr('opacity', 1);
    element.data("over", false);
    text.toFront();
    text.animate({ opacity: 0.2 }, 100);
}

element.mouseout(hoverOutHandler);
element.mouseover(hoverInHandler);

function hoverInHandler(e){
    this.animate({
        transform: 's1.2' }, 100, "elastic");
    animateElement();
}

function hoverOutHandler(e){
    this.animate({
        transform: 's1' }, 101);
    animateElementOff();
}

Answer №2

After receiving valuable assistance from Ian, I made significant progress with my project. I decided to provide an update with additional details that may benefit others.

I also successfully implemented a clickable link within the content.

var ONEgrp = paper1.set();

// Main Path ONE
var ONE = paper1.path("M340.1064,218.2627l97.8281-75.5117c-39.5898-48.9438-100.123-80.2485-167.9785-80.2485V186.019C298.0166,186.019,323.1533,198.5244,340.1064,218.2627z");
ONE.attr({parent: 'ONEgrp',fill: "#EFA35A",stroke:"#fff",'stroke-width':1, cursor: 'pointer'}).data('id', 'ONE');

// Text for ONE
var ONEtxt = paper1.text(340, 145, "Total Rewards\nManagement\nT1/GR1");
ONEtxt.attr('fill', '#000');
ONEtxt.attr('font-size', '14px');
ONEtxt.attr('font-family', 'Helvetica, Arial, sans-serif');
ONEtxt.attr('font-weight', 400);

// Define animation effects for mouseover and mouseout events
var mouseover_anim = Raphael.animation({transform: 's1.2' }, 100, "elastic");
var mouseout_anim = Raphael.animation({transform: 's1.2' }, 100, "elastic");
var mouseover_anim2 = Raphael.animation({transform: 's1' }, 100, "elastic");
var mouseout_anim2 = Raphael.animation({transform: 's1' }, 100, "elastic");

// Implement mouseover and mouseout functionality for interaction with ONE element
ONE.mouseover(function(){
    ONE.animate(mouseover_anim);
    ONEtxt.animateWith(ONE,mouseover_anim,mouseout_anim);
    if(!ONE.data("over")) {
        ONE.attr('opacity',
        ONE.attr('opacity')*0.90); 
        ONE.toFront();
        ONE.data("over",true);
        ONEtxt.toFront();
        ONEtxt.data("over",true);
    }
    if(!ONEtxt.data("over")) {
        ONEtxt.toFront();
        ONEtxt.data("over",true);
    }
});

ONE.mouseout(function(){
    ONE.animate(mouseover_anim2);
    ONEtxt.animateWith(ONE,mouseover_anim2,mouseout_anim2);
    ONE.attr('opacity',1);
    ONE.data("over",false);
    // Code for bringing other elements to front on mouseout event
});

// Function for mouse hover effect
function hovering(e){
    ONE.animate({
        transform: 's1.2' }, 100, "elastic");
}

// Function for removing mouse hover effect
function hoverout(e){
    ONE.animate({
        transform: 's1' }, 100);
}

// Assigning mouseout and mouseover functions to ONE element
ONE.mouseout(hoverout);
ONE.mouseover(hovering);

// Click event for navigating to a specific URL when ONE element is clicked
ONE.click(function() {
    window.location.href = "/adimLink?id=18458";
});

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

Update the src attribute of img elements using regular expressions

Figured it out in case anyone might find it useful, here's the solution: var feed = feeds.entries[i].content; var parsedFeed = feed.replace(/src=/gi, "tempsrc="); var tmpHolder = document.createElement('div'); tmpHolder.innerH ...

What is the best way to filter an object in AngularJS based on its properties?

I am faced with the issue of filtering two arrays of objects. Below is an example: $scope.countries = [ {'id' : 1, 'country_name':'India'}, {'id' : 10, 'country_name':'Australia'} ...

Utilizing AngularJS with dual controllers within a single view

I recently started working on an angularJS web app using a purchased template that has all its controllers, routes, and directives in a single file called app.js. This is my first dive into angularJS and front-end development. Hoping to become a Full Stac ...

The dynamic duo: Formik meets Material-UI

Trying to implement Formik with Material-UI text field in the following code: import TextField from '@material-ui/core/TextField'; import { Field, FieldProps, Form, Formik, FormikErrors, FormikProps } from 'formik'; import ...

Show information from a database and automatically refresh the displayed records with any new data added to the database

My goal is to show records from a database and have them automatically update when a new one is added. To achieve this, I am using a combination of PHP and JavaScript. Specifically, I aim to load a page that displays tags beneath a video. When a user ente ...

Performing double string splitting with multiple separators in javascript

If I have a string like a.b.c.d#.e.f.g.h#.i.j.k.l and want to split it first by "#" and then by ".": str = a.b.c.d#.e.f.g.h#.i.j.k.l res = str.split("#") res[0] will contain a.b.c.d after the first split. Now, I need to further split this data. Is th ...

Use ajax, javascript, and php to insert information into a database

Issue at Hand: I am trying to extract the subject name from the admin and store it in the database. Following that, I aim to display the query result on the same webpage without refreshing it using Ajax. However, the current code is yielding incorrect outp ...

Is it possible for me to utilize a validation function to display error messages within a specific span id tag?

document.getElementById("button1").addEventListener("click", mouseOver1); function mouseOver1(){ document.getElementById("button1").style.color = "red"; } document.getElementById("button2").addEventListener("click", mouseOver); function mous ...

What is the best way to share variable values between different components in React?

I initially assumed that setting a prop would handle the value within the receiving component, but now I realize that I want to export the value to other components. For example, consider this reusable component: RegionButtons.jsx file import React, { us ...

Having trouble getting $.ajax to function properly in conjunction with fullcalendar js?

Currently in the process of utilizing the Smart Admin Theme, specifically focusing on the functionality within the calendar page. The calendar's core features are operational, allowing for the creation and placement of new events on the map. My curr ...

Utilize typehead.js in Python Django to retrieve an updated data list directly from the database

file.js var source = new Bloodhound({ hint: false, datumTokenizer: Bloodhound.tokenizers.obj.whitespace("description"), queryTokenizer: Bloodhound.tokenizers.whitespace, // /a_c/p_s/?term=d&category=all remote: "/a ...

What is the best way to add up the attributes of objects within an array and save the total to the main

I have a collection of objects, illustrated here: var obj = { "ABC" : { "name" : "ABC", "budget" : 0, "expense" : 0, "ledgers" : [{ "Actual1920": 10, "Budget1920": 20, }, { "Actual1920": 10, ...

Javascript function fails to run smoothly during rapidscrolling

I'm facing an issue with my JavaScript code that adjusts the transparency of the navigation bar while scrolling. It works perfectly when scrolling slowly, but when the scrolling speed is fast, it seems like the function is not triggered and the navbar ...

When using Vue2, pushing a string to an array simply replaces the existing string instead of appending it

My current task involves manipulating a local data array by adding and removing strings within a method. However, I have noticed that my logic always results in the array containing only a single string passed to the updateIdArr method. Even after removin ...

Differences in results occur when JavaScript function declarations are used in both Native browser and Node.js environments

When running the code below, the results differ between Browser and Node.js environments. In the browser, the result is a. In Node.js, the result is b. if (1) { function foo() { return 'a'; } } else { function foo() { return 'b&ap ...

Merge SVG paths that do not intersect with a stroke running through the center

Does anyone know how to merge paths in CSS when the stroke-line cuts through the path, even with stroke: black; set? I attempted combining them by just adding all the d parameters together manually but it doesn't seem to work correctly. The paths in ...

Whenever I attempt to search for an element within my useState array, my component automatically re-renders

Currently working on a React project and facing an issue with the search Input. Whenever I type something in the Input field, the entire component re-renders, triggering an API recall and clearing out the text in the Input. Even after merging the search co ...

Execute a Vue.js script once all Axios calls have been resolved

In this scenario, it is necessary to execute the carResult function only after all axios requests have been completed. Placing it inside the success method of method2 won't work because the component ends up executing the code twice. It would be great ...

Utilize jQuery to style the background of the webpage, while excluding the Modal element when using Bootstrap

I'm currently working on implementing foggy.js () to create a blurred background effect for Bootstrap's Modal. While I've successfully blurred all elements in the background, the Modal Popup itself is also appearing blurry. So my question is ...

Using AngularJS to make repeated API calls with modified parameters

Issue - My task involves consolidating the response array into one. I am making consecutive calls to the same API, with a dynamic 'skip' parameter based on the last response. Call #1 - api(id, skip=0) Call #2 - api(id, skip+1) ... Below is the ...