svg.js, click event does not fire when animation is running - animation

I try to bind a click event on symbol in a svg.
When a element spinns in the symbol, the click event is not fired, stops/pauses the animation, the click event fires.
How can i fix this, that the click events get fired every time i click on it, regardless if the animations run or not.
.as-console-wrapper{
display: none!important;
}
<!doctype html>
<html lang="de">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title>Schematic</title>
<script src="https://cdn.jsdelivr.net/npm/#svgdotjs/svg.js#3.0/dist/svg.min.js"></script>
<!--<script src="assets/js/vue.min.js"></script>-->
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.12/vue.common.dev.min.js"></script>
<script>
const color = {
blue: "#007bff",
indigo: "#6610f2",
purple: "#6f42c1",
pink: "#e83e8c",
red: "#dc3545",
orange: "#fd7e14",
yellow: "#ffc107",
green: "#28a745",
teal: "#20c997",
cyan: "#17a2b8",
white: "#fff",
gray: "#6c757d",
"gray-dark": "#343a40",
primary: "#007bff",
secondary: "#6c757d",
success: "#28a745",
info: "#17a2b8",
warning: "#ffc107",
danger: "#dc3545",
light: "#f8f9fa",
dark: "#343a40"
};
let baseColor = {
background: "#000",
"fill-opacity": 0.5,
stroke: color.white,
"stroke-width": 1,
"stroke-opacity": 0.5
};
let pipeColor = {
fill: color.blue,
opacity: 1
};
let pumpColor = {
fill: color.gray,
"fill-opacity": 0.8
}
document.addEventListener("DOMContentLoaded", () => {
// parent drawing
let draw = SVG().addTo('#schematic').size("100%", 500);
let pumpGroup = draw.symbol();
pumpGroup.click(function () {
alert("Pump clicked!");
});
let height = 50;
let radius = 30;
let chase = pumpGroup.rect(80, height).attr(baseColor).move(0, 0); // 520, 370
let motor1 = pumpGroup.circle(radius).attr(pumpColor).move(45, (height / 2) - radius / 2); // 525, 380
let motor2 = pumpGroup.circle(radius).attr(pumpColor).move(5, (height / 2) - radius / 2); // 565, 380
let fan1 = pumpGroup.image("https://cdn0.iconfinder.com/data/icons/screw/512/fan-ventilator-propeller-rotor-motion-512.png").scale(0.05).move(940, 240); //.animate().rotate(360, 256 + 940, 256 + 240).loop();
let fan2 = pumpGroup.image("https://cdn0.iconfinder.com/data/icons/screw/512/fan-ventilator-propeller-rotor-motion-512.png").scale(0.05).move(140, 240);
//
// 1 = slave, 2 = master
let fant1Runner = fan1.animate(1500).ease("-").rotate(360, 256 + 940, 256 + 240).loop().timeline().pause();
let fant2Runner = fan2.animate(1500).ease("-").rotate(360, 256 + 140, 256 + 240).loop().timeline().pause();
setInterval(() => {
fant2Runner.play();
fant1Runner.play();
setTimeout(() => {
fant2Runner.pause();
fant1Runner.pause();
}, 2500)
}, 5000);
draw.use(pumpGroup).move(10, 10).click(() => {
alert("Clicked on pump!");
});
});
</script>
</head>
<body>
<div id="app">
<div id="schematic"></div>
</div>
</body>
</html>
For demsonstation i create a minimal snippet.
The fans start spinning after 5sec, run then for 2.5 sec and stops.
As written above, when the fans spin, no click fires.
Thanks for any advise.

Related

NVD3 - show tick lines only on axes

TLDR: I have an NVD3 graph that shows tick lines all across the axis, but I would like to change it so it only displays on the axis lines if possible.
Here is a live example:
var app = angular.module('plunker', ['nvd3']);
app.controller('MainCtrl', function($scope) {
$scope.options = {
chart: {
type: 'lineChart',
height: 450,
margin : {
top: 20,
right: 20,
bottom: 80,
left: 55
},
x: function(d){ return d.x; },
y: function(d){ return d.y; },
useInteractiveGuideline: true,
xAxis: {
axisLabel: 'Timeline',
tickFormat: function(d) {
return d3.time.format('%B %d')(new Date(d))
},
ticks: 6,
showMaxMin: false
},
yAxis: {
axisLabel: 'Molecular density (kg/m^3)',
tickFormat: function(d){
return d3.format('.02f')(d);
},
axisLabelDistance: -10,
showMaxMin: false
}
}
};
$scope.data = [{"key":"K7 molecules","values":[{"x":1435708800000,"y":8},{"x":1435795200000,"y":9},{"x":1435881600000,"y":8},{"x":1435968000000,"y":8},{"x":1436054400000,"y":9},{"x":1436140800000,"y":9},{"x":1436227200000,"y":8},{"x":1436313600000,"y":8},{"x":1436400000000,"y":9},{"x":1436486400000,"y":9},{"x":1436572800000,"y":7},{"x":1436659200000,"y":8}],"area":true,"color":"#0CB3EE"},{"key":"N41 type C molecules","values":[{"x":1435708800000,"y":8},{"x":1435795200000,"y":7},{"x":1435881600000,"y":8},{"x":1435968000000,"y":9},{"x":1436054400000,"y":7},{"x":1436140800000,"y":9},{"x":1436227200000,"y":8},{"x":1436313600000,"y":9},{"x":1436400000000,"y":9},{"x":1436486400000,"y":9},{"x":1436572800000,"y":9},{"x":1436659200000,"y":8}],"area":true,"color":"#383838"}];
});
<!DOCTYPE html>
<html ng-app="plunker">
<head>
<meta charset="utf-8" />
<title>Angular-nvD3 Line Chart</title>
<script>document.write('<base href="' + document.location + '" />');</script>
<link rel="stylesheet" href="style.css" />
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/nvd3/1.8.1/nv.d3.min.css"/>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.9/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.6/d3.min.js" charset="utf-8"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/nvd3/1.8.1/nv.d3.min.js"></script>
<script src="https://rawgit.com/krispo/angular-nvd3/v1.0.1/dist/angular-nvd3.js"></script>
<script src="app.js"></script>
</head>
<body ng-controller="MainCtrl">
<nvd3 options="options" data="data" class="with-3d-shadow with-transitions"></nvd3>
</body>
</html>
Is there any way I could make the tick lines appear just on the axes line only? To make it clear, this is what it looks like:
I used a different library to generate the following plot, and I would like the tick lines to appear just on the axis lines like this example instead:
It appears that there is no real way to do this with NVD3 as it does not provide a way to show tick marks on the axis. However, we could add our own tick marks by fetching the chart SVG and then modifying it.
I've attached an example that adds tick marks to X-Axis, and it is basically slightly modified based on this jsfiddle here: http://jsfiddle.net/3r88bgjw
var data;
data = [{
values: [],
}, ];
var i, x;
var prevVal = 3000;
var tickCount = 2000;
for (i = 0; i < tickCount; i++) {
x = 1425096000 + i * 10 * 60; // data points every ten minutes
if (Math.random() < 0.8) { // add some gaps
prevVal += (Math.random() - 0.5) * 500;
if (prevVal <= 0) {
prevVal = Math.random() * 100;
}
data[0].values.push({
x: x * 1000,
y: prevVal
});
}
}
var chart;
nv.addGraph(function() {
chart = nv.models.historicalBarChart();
chart.xScale(d3.time.scale()) // use a time scale instead of plain numbers in order to get nice round default values in the axis
.color(['#68c'])
.useInteractiveGuideline(true) // check out the css that turns the guideline into this nice thing
.margin({
"left": 80,
"right": 50,
"top": 20,
"bottom": 30,
})
.noData("There is no data to display.")
.duration(0);
var tickMultiFormat = d3.time.format.multi([
["%-I:%M%p", function(d) {
return d.getMinutes();
}], // not the beginning of the hour
["%-I%p", function(d) {
return d.getHours();
}], // not midnight
["%b %-d", function(d) {
return d.getDate() != 1;
}], // not the first of the month
["%b %-d", function(d) {
return d.getMonth();
}], // not Jan 1st
["%Y", function() {
return true;
}]
]);
chart.xAxis
.showMaxMin(false)
.tickPadding(10)
.tickFormat(function(d) {
return tickMultiFormat(new Date(d));
});
chart.yAxis
.tickFormat(d3.format(",.0f"));
var svgElem = d3.select('#chart svg');
svgElem
.datum(data)
.transition()
.call(chart);
// make our own x-axis tick marks because NVD3 doesn't provide any
var tickY2 = chart.yAxis.scale().range()[1];
var lineElems = svgElem
.select('.nv-x.nv-axis.nvd3-svg')
.select('.nvd3.nv-wrap.nv-axis')
.select('g')
.selectAll('.tick')
.data(chart.xScale().ticks())
.append('line')
.attr('class', 'x-axis-tick-mark')
.attr('x2', 0)
.attr('y1', tickY2 + 7)
.attr('y2', tickY2)
.attr('stroke-width', 3);
// set up the tooltip to display full dates
var tsFormat = d3.time.format('%b %-d, %Y %I:%M%p');
var contentGenerator = chart.interactiveLayer.tooltip.contentGenerator();
var tooltip = chart.interactiveLayer.tooltip;
tooltip.contentGenerator(function(d) {
d.value = d.series[0].data.x;
return contentGenerator(d);
});
tooltip.headerFormatter(function(d) {
return tsFormat(new Date(d));
});
return chart;
});
<div>Try resizing the panel to see the various types of time labels.</div>
<br>
<div id="chart">
<svg></svg>
</div>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/nvd3/1.8.4/nv.d3.min.css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.6/d3.min.js" charset="utf-8"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/nvd3/1.8.4/nv.d3.min.js"></script>

Amcharts5 Floating Barchart over two axes

I started off with this example: https://www.amcharts.com/demos/floating-bar-chart/ but want the floating-aspect also cover a date axis. This way I will be able to color a rectangular area in my charts.
I made the following changes:
Changed the x-axis to a date axis
Changed the y-axis to a value axis
Changed the data correspondingly
Changed the data-fields in the series-definition to use openValueXField, valueXField for the dates and openValueYField and valueYField for the values
Something (vertical colored lines) are displayed in the most left part of the chart but no colored areas.
When using values for both axes it works perfectly but not with dates. I hope some of you knows what is wrong here. The Amcharts Demo's only provide example with one axis.
The two source codes are included hereafter.
//
// Source Code for two numeric axis -> working
//
<meta content="text/html;charset=utf-6" http-equiv="Content-Type">
<meta content="utf-8" http-equiv="encoding">
<!-- Styles -->
<style>
#chartdiv {
width: 100%;
height: 500px;
}
</style>
<!-- Resources -->
<script src="https://cdn.amcharts.com/lib/5/index.js"></script>
<script src="https://cdn.amcharts.com/lib/5/xy.js"></script>
<script src="https://cdn.amcharts.com/lib/5/themes/Animated.js"></script>
<!-- Chart code -->
<script>
am5.ready(function() {
// Create root element
// https://www.amcharts.com/docs/v5/getting-started/#Root_element
var root = am5.Root.new("chartdiv");
// Set themes
// https://www.amcharts.com/docs/v5/concepts/themes/
root.setThemes([
am5themes_Animated.new(root)
]);
// Create chart
// https://www.amcharts.com/docs/v5/charts/xy-chart/
var chart = root.container.children.push(am5xy.XYChart.new(root, {
panX: false,
panY: false,
wheelX: "panX",
wheelY: "zoomX",
layout: root.verticalLayout
}));
// Add legend
// https://www.amcharts.com/docs/v5/charts/xy-chart/legend-xy-series/
var legend = chart.children.push(am5.Legend.new(root, {
centerX: am5.p50,
x: am5.p50
}))
var colors = chart.get("colors");
// Data
var data = [{
name: "John",
startTime: 8,
endTime: 11,
startValue: 10,
endValue: 14,
columnSettings: {
stroke: colors.getIndex(1),
fill: colors.getIndex(1)
}
}, {
name: "Joe",
startTime: 10,
endTime: 13,
startValue: 12,
endValue: 17,
columnSettings: {
stroke: colors.getIndex(3),
fill: colors.getIndex(3)
}
}];
// Create axes
// https://www.amcharts.com/docs/v5/charts/xy-chart/axes/
var yAxis = chart.yAxes.push(
am5xy.ValueAxis.new(root, {
renderer: am5xy.AxisRendererY.new(root, {pan:"zoom"}),
})
);
var xAxis = chart.xAxes.push(
am5xy.ValueAxis.new(root, {
renderer: am5xy.AxisRendererX.new(root, {pan:"zoom"}),
})
);
// Add series
// https://www.amcharts.com/docs/v5/charts/xy-chart/series/
var series = chart.series.push(am5xy.ColumnSeries.new(root, {
name: "Income",
xAxis: xAxis,
yAxis: yAxis,
openValueXField: "startTime",
valueXField: "endTime",
openValueYField: "startValue",
valueYField: "endValue",
sequencedInterpolation: true
}));
series.columns.template.setAll({
height: am5.percent(100),
templateField: "columnSettings",
tooltipText: "[bold]{name}[/]\n{categoryY}: {valueX}"
});
series.data.setAll(data);
// Make stuff animate on load
// https://www.amcharts.com/docs/v5/concepts/animations/
series.appear();
chart.appear(1000, 100);
}); // end am5.ready()
</script>
<!-- HTML -->
<div id="chartdiv"></div>
91,31 43%
//
// Source Code for one date and one numeric axis -> NOT working
//
<meta content="text/html;charset=utf-8" http-equiv="Content-Type">
<meta content="utf-8" http-equiv="encoding">
<!-- Styles -->
<style>
#chartdiv {
width: 100%;
height: 500px;
}
</style>
<!-- Resources -->
<script src="https://cdn.amcharts.com/lib/5/index.js"></script>
<script src="https://cdn.amcharts.com/lib/5/xy.js"></script>
<script src="https://cdn.amcharts.com/lib/5/themes/Animated.js"></script>
<!-- Chart code -->
<script>
am5.ready(function() {
// Create root element
// https://www.amcharts.com/docs/v5/getting-started/#Root_element
var root = am5.Root.new("chartdiv");
// Set themes
// https://www.amcharts.com/docs/v5/concepts/themes/
root.setThemes([
am5themes_Animated.new(root)
]);
// Create chart
// https://www.amcharts.com/docs/v5/charts/xy-chart/
var chart = root.container.children.push(am5xy.XYChart.new(root, {
panX: false,
panY: false,
wheelX: "panX",
wheelY: "zoomX",
layout: root.verticalLayout
}));
// Add legend
// https://www.amcharts.com/docs/v5/charts/xy-chart/legend-xy-series/
var legend = chart.children.push(am5.Legend.new(root, {
centerX: am5.p50,
x: am5.p50
}))
var colors = chart.get("colors");
// Data
var data = [{
name: "John",
startTime: new Date(2021, 1, 28),
endTime: new Date(2021, 3, 17),
startValue: 10,
endValue: 14,
columnSettings: {
stroke: colors.getIndex(1),
fill: colors.getIndex(1)
}
}, {
name: "Joe",
startTime: new Date(2021, 2, 5),
endTime: new Date(2021, 5, 7),
startValue: 12,
endValue: 17,
columnSettings: {
stroke: colors.getIndex(3),
fill: colors.getIndex(3)
}
}];
// Create axes
// https://www.amcharts.com/docs/v5/charts/xy-chart/axes/
var yAxis = chart.yAxes.push(
am5xy.ValueAxis.new(root, {
renderer: am5xy.AxisRendererY.new(root, {pan:"zoom"}),
})
);
var xAxis = chart.xAxes.push(
am5xy.DateAxis.new(root, {
renderer: am5xy.AxisRendererX.new(root, {
pan:"zoom",
minimumDate: new Date(2021, 1, 18),
maximumDate: new Date(2021, 7, 20),
}),
})
);
// Add series
// https://www.amcharts.com/docs/v5/charts/xy-chart/series/
var series = chart.series.push(am5xy.ColumnSeries.new(root, {
name: "Income",
xAxis: xAxis,
yAxis: yAxis,
openValueXField: "startTime",
valueXField: "endTime",
openValueYField: "startValue",
valueYField: "endValue",
sequencedInterpolation: true
}));
series.columns.template.setAll({
height: am5.percent(100),
templateField: "columnSettings",
tooltipText: "[bold]{name}[/]\n{categoryY}: {valueX}"
});
series.data.setAll(data);
// Make stuff animate on load
// https://www.amcharts.com/docs/v5/concepts/animations/
series.appear();
chart.appear(1000, 100);
}); // end am5.ready()
</script>
<!-- HTML -->
<div id="chartdiv"></div>
94,3 97%

Rotate marker with animation in Openlayers

I have this code:
this.posFeature = new ol.Feature({
geometry: new ol.geom.Point(ol.proj.fromLonLat([-5.7,43.5])),
name: 'pos'
});
var posStyle = new ol.style.Style({
image: new ol.style.Icon({
anchor: [10, 10],
anchorXUnits: 'pixels',
anchorYUnits: 'pixels',
src: 'car.svg'
})
});
this.posFeature.setStyle(posStyle);
this.markerPosSource = new ol.source.Vector({features: [this.posFeature]});
this.layerPos = new ol.layer.Vector({source: this.markerPosSource});
map.addLayer(this.layerPos);
I would like to rotate the icon with an animation (in its rotation). Is it possible? If not, how to rotate without animation?
Thanks in advance!
To smoothly animate a rotation calculate the required rotation based on elapsed time each time the map rendered, e.g. for a complete rotation every 10 seconds:
<!DOCTYPE html>
<html>
<head>
<title>Icon Symbolizer</title>
<link rel="stylesheet" href="https://openlayers.org/en/v6.4.3/css/ol.css" type="text/css">
<script src="https://openlayers.org/en/v6.4.3/build/ol.js"></script>
<style>
html, body, .map {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
}
</style>
</head>
<body>
<div id="map" class="map"></div>
<script>
var iconFeature = new ol.Feature({
geometry: new ol.geom.Point([0, 0]),
name: 'Null Island',
population: 4000,
rainfall: 500
});
var iconStyle = new ol.style.Style({
image: new ol.style.Icon({
anchor: [0.5, 1],
src: 'https://openlayers.org/en/v6.4.3/examples/data/icon.png'
})
});
iconFeature.setStyle(iconStyle);
var vectorSource = new ol.source.Vector({
features: [iconFeature]
});
var vectorLayer = new ol.layer.Vector({
source: vectorSource
});
var map = new ol.Map({
layers: [vectorLayer],
target: document.getElementById('map'),
view: new ol.View({
center: [0, 0],
zoom: 3
})
});
var startTime = new Date().getTime();
map.on('rendercomplete', function(e) {
var elapsedTime = e.frameState.time - startTime;
var rotation = elapsedTime / 10000 * Math.PI;
iconStyle.getImage().setRotation(rotation);
iconFeature.changed();
});
</script>
</body>
</html>
To rotate it use rotation (NB use radians not degrees)
var posStyle = new ol.style.Style({
image: new ol.style.Icon({
anchor: [10, 10],
anchorXUnits: 'pixels',
anchorYUnits: 'pixels',
src: 'car.svg',
rotation: Math.PI/2
})
});

I don't know how to change a color in a d3.js US map when hovered over

I have this map of the USA. I know how to bind other data, change colors of states but the only thing I don't know how to change the default orangish color when a state is hovered over.
You can find it here as well: http://blockbuilder.org/malcolm-decuire/34d2ce39d3b8c2f8a577
<!DOCTYPE html>
<meta charset="utf-8">
<body>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script src="http://d3js.org/topojson.v1.min.js"></script>
<script src="http://datamaps.github.io/scripts/datamaps.all.min.js?v=1"></script>
<h2> American Lynches | 1830-1970</h2>
<div id="map" style="position: relative; width: 900px; max-height: 900px;"></div>
<script>
var map = new Datamap({
scope: 'usa',
element: document.getElementById('map'),
geographyConfig:{
highlightBorderColor: '#bada55',
popupTemplate: function(geography, data){
return '<div class="hoverinfo">' + geography.properties.name + ' White/Black ' + data.LynchWhite + ' / ' + data.LynchBlack
},
},
height: 500,
fills: {
'none': '#999999',
'White': '#CC4731',
'Black': '#306596',
},
data: {
"AZ": {
"fillKey": "White",
"LynchWhite": 31,
"LynchBlack": 0
},
...
}
})
//keep this code
map.bubbles([ ], {
popupTemplate: function(geography, data) {
return "<div class='hoverinfo'>It is " + data.name + "</div>";
}
});
</script>
<script>
var ordinal = d3.scale.ordinal()
.domain(["white", "black", "none"])
.range([ "rgb(204,71,49)", "rgb(48,101,150)", "rgb(153,153,153"]);
var svg = d3.select("svg");
svg.append("g")
.attr("class", "legendOrdinal")
.attr("transform", "translate(450,450)");
var legendOrdinal = d3.legend.color()
.shape("path", d3.svg.symbol().type("triangle-up").size(150)())
.shapePadding(10)
.scale(ordinal);
svg.select(".legendOrdinal")
.call(legendOrdinal);
</script>
</body>
According to the documentation, it's controlled by the highlightFillColor config option:
geographyConfig:{
highlightFillColor: '#FC8D59'
}

Rotate an rectangle with transform and Raphaël, how?

I tried the code:
paper.rect(100, 100, 300,300).animate({transform :"t0,0r120t-0,0"}, 2000, "bounce");
in the stie http://raphaeljs.com/playground.html
And it workes greate, but in my code I cant get the object to rotate on place. Please help? The one I want to rotate is the var blueRect.
Tis is my code:
<!DOCTYPE html>
<html lang="sv">
<head>
<meta charset="utf-8" />
<title>SVG/VLM</title>
<link href="stylesheet.css" media="screen" rel="stylesheet" type="text/css" />
<style>
#artboard{
width: 240px;
height: 150px;
}
</style>
<script src="raphael.js"></script>
<script type="text/javascript">
var paper;
var blueRect;
var redRect;
var rightButton;
var stopButton;
var xEnd;
function init(){
paper = Raphael("artboard");
// Bakgrunden
var background = paper.rect( 0, 0, "100%", "90px", 0 );
background.attr({fill: "#f3f3ff", "stroke-width": 1, "stroke": "#000"});
// Blåa rektangeln
blueRect = paper.rect( 35, 20, "50px", "50px", 0);
blueRect.attr({fill: "#aaaaff", "stroke-width": 3, "stroke": "#000"});
// Röda rektangeln
redRect = paper.rect( 150, 20, "50px", "50px", 0);
redRect.attr({fill: "#ffaaaa", "stroke-width": 3, "stroke": "#000"});
//Knapparna
rightButton = paper.rect(5, 100, "50px", "22px", 0);
rightButton.attr("fill", "#ff0000");
leftButton = paper.rect(65, 100, "50px", "22px", 0);
leftButton.attr("fill", "#00ff00");
sidewaysButton = paper.rect(125, 100, "50px", "22px", 0);
sidewaysButton.attr("fill", "#0000ff");
stopButton = paper.rect(185, 100, "50px", "22px", 0);
stopButton.attr("fill", "#000");
xEnd = 150;
// Kör funktionen sideways()
go();
};
function go(){
rightButton.click(
function rotateRight(){
blueRect.animate({transform:"t0,0r120t-0,0"}, 2000, "bounce");
});
sidewaysButton.click(
function sine(){
if( xEnd == 150 )
xEnd = 50;
else
xEnd = 150;
redRect.animate( {x: xEnd}, // Attributet som ska animeras följt av till vilket värde den ska animeras
1000, // Tiden
"sine", // Ease funktion
function (){ sine(); } // Anropar sig själv igen för att upprepa funktionen.
);
});
stopButton.click(
function stop(){
redRect.stop();
});
}
</script>
</head>
<body onload="init()">
<div id="artboard"></div>
</body>
</html>
And I'm sorry about all the Swedish comments, hope that dosen't matter for you to understand my code.
In this particular case you would need to get it to rotate around its center by specifying the centre points, so the transform would look like...
blueRect.animate({transform:"r120,60,45"}, 2000, "bounce")
If its variable where it will be, you could get the centre point from getBBox()
jsfiddle

Resources