I am using Fabric.js to display text on CANVAS.. which works great and displays text like below
What I am trying to achieve is Text effect like below below
Instead of plain.. is it possible to do so?
Here is my code..
<!DOCTYPE html>
<head>
<meta charset="utf-8">
<title>fabric.js-simple text display</title>
<!-- Get version 1.1.0 of Fabric.js from CDN -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.1.0/fabric.all.min.js" ></script>
<!-- Get the highest 1.X version of jQuery from CDN. Required for ready() function. -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<body>
<!-- A canvas tag is required or
Fabric.js doesn't know where to draw. -->
<canvas id="c" style="border:1px solid black;" ></canvas>
</body>
<script>
// Place script tags at the bottom of the page.
// That way progressive page rendering and
// downloads are not blocked.
// Run only when HTML is loaded and
// DOM properly initialized (courtesy jquery)
$(function () {
// Obtain a canvas drawing surface from fabric.js
var canvas = new fabric.Canvas('c');
// Create a text object.
// Does not display it-the canvas doesn't
// know about it yet.
var hi = new fabric.Text('hello, world.', {
left: canvas.getWidth() / 2,
top: canvas.getHeight() / 2
});
// Attach it to the canvas object, then (re)display
// the canvas.
canvas.add(hi);
});
</script>
</head>
</html>
Also Look at this fiddle. http://jsfiddle.net/swesh/c7s9x2fh/199/
var canvas = new fabric.Canvas('c')
var text= "Happy Birthday"
var headingText = [];
var startAngle = -58;
var textLength = text.length;
var r = getTranslationDistance(text);
var j=-1;
var angleInterval = 116/textLength;
for(var iterator=(-textLength/2), i=textLength-1; iterator<textLength/2;iterator++,i--){
var rotation = 90-(startAngle+(i)*angleInterval) ;
headingText.push(new fabric.IText(text[i], {
angle : j*((startAngle)+(i*angleInterval)),
shadow: 'rgba(0,0,0,0.5) 5px 5px 5px',
fontSize:28,
left: (r)*Math.cos((Math.PI/180)*rotation),
top: (r)*Math.sin((Math.PI/180)*rotation)
}));
}
var group2 = new fabric.Group(headingText, { left: 0, top: canvas.height/2,fontFamily: 'Arial', strokeWidth: 1,
strokeStyle:"#fff"});
canvas.add(group2);
function getTranslationDistance(text){
var boundingRectangle = $("<div id='tempdiv' style='display:table-cell;font- family:Arial; font-size:28px;'>"+text+"</div>").appendTo("#main");
var translationDistance = $(boundingRectangle).width();
$(boundingRectangle).remove();
return translationDistance;
}
I haven't found any fabric js library function that will generate valley text.
But you may try the curved text using http://tympanus.net/Development/Arctext/.Hope this helps you
To use bent text on HTML5 canvas go to this
http://www.html5canvastutorials.com/labs/html5-canvas-text-along-arc-path/
I got a working example here Demo: http://jsfiddle.net/NHs8t/
Thanks everyone for your help
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<title> - jsFiddle demo</title>
<script type='text/javascript' src='//code.jquery.com/jquery-1.9.1.js'></script>
<link rel="stylesheet" type="text/css" href="/css/result-light.css">
<script type='text/javascript' src="http://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.2.0/fabric.all.min.js"></script>
<style type='text/css'>
canvas { border:1px solid #000; }
.controles { margin:50px 0; }
</style>
<script type='text/javascript'>//<![CDATA[
$(window).load(function(){
/***** Required : http://fabricjs.com *****/
var CurvedText = (function() {
/**
* Constructor
* #method curvedText
* #param canvas
* #param {object} options
*/
function CurvedText( canvas, options ){
// Options
this.opts = options || {};
for ( var prop in CurvedText.defaults ) {
if (prop in this.opts) { continue; }
this.opts[prop] = CurvedText.defaults[prop];
}
this.canvas = canvas;
this.group = new fabric.Group([], {selectable: this.opts.selectable});
this.canvas.add( this.group ) ;
this._forceGroupUpdate();
this.setText( this.opts.text );
}
/**
* #method set
* #param {string} param
* #param value
* #return false if the param name is unknown
*/
CurvedText.prototype.set = function( param, value ) {
if ( this.opts[param] !== undefined ) {
this.opts[param] = value;
if ( param === 'fontSize' || param === 'fontWeight' ) {
this._setFontStyles();
}
if ( param === 'selectable' ) {
this.group.selectable = value;
}
if ( param === 'angle' ) {
this._forceGroupUpdate();
}
this._render();
return true;
} else {
return false;
}
};
/**
* #method get
* #param {string} param
* #return value of param, or false if unknown
*/
CurvedText.prototype.get = function( param ) {
this._render();
if ( this.opts[param] !== undefined ) {
return this.opts[param];
} else {
return false;
}
};
/**
* #method getParams
* #return {object} value of every options
*/
CurvedText.prototype.getParams = function() {
this._render();
return this.opts;
};
/**
* Center the group in canvas
* #method center
* #return {object} with top and left
*/
CurvedText.prototype.center = function() {
this.opts.top = this.canvas.height / 2;
this.opts.left = this.canvas.width / 2;
this._render();
return { top:this.opts.top, left:this.opts.left };
};
/**
* Remove all letters from canvas
* #method remove
*/
CurvedText.prototype.remove = function() {
var size = this.group.size();
for ( var i=size; i>=0; i-- ){
this.group.remove( this.group.item(i) );
}
this.canvas.renderAll();
};
/**
* Used to change the text
* #method setText
* #param {string} newText
*/
CurvedText.prototype.setText = function( newText ) {
while ( newText.length !== 0 && this.group.size() >= newText.length ) {
this.group.remove( this.group.item( this.group.size()-1 ) );
}
for ( var i=0; i<newText.length; i++ ){
if ( this.group.item(i) === undefined ){
var letter = new fabric.Text(newText[i], {
selectable: true
});
this.group.add( letter );
}
else{
this.group.item(i).text = newText[i];
}
}
this.opts.text = newText;
this._setFontStyles();
this._render();
};
/**
* Update font size and weight
* #private
* #method _setFontStyles
*/
CurvedText.prototype._setFontStyles = function() {
for ( var i=0; i<this.group.size(); i++ ){
this.group.item(i).setFontSize( this.opts.fontSize );
this.group.item(i).fontWeight = this.opts.fontWeight ;
}
};
/**
* Force update group scale and angles
* #private
* #method _forceGroupUpdate
*/
CurvedText.prototype._forceGroupUpdate = function() {
this.group.setAngle( this.opts.angle );
this.group.scaleX = this.opts.scaleX;
this.group.scaleY = this.opts.scaleY;
this._render();
};
/**
* calculate the position and angle of each letter
* #private
* #method _render
*/
CurvedText.prototype._render = function() {
var curAngle=0,angleRadians=0, align=0;
// Object may have been moved with drag&drop
if ( this.group.hasMoved() ) {
this.opts.top = this.group.top;
this.opts.left = this.group.left;
}
this.opts.angle = this.group.getAngle();
this.opts.scaleX = this.group.scaleX;
this.opts.scaleY = this.group.scaleY;
// Text align
if ( this.opts.align === 'center' ) {
align = ( this.opts.spacing / 2) * ( this.group.size() - 1) ;
} else if ( this.opts.align === 'right' ) {
align = ( this.opts.spacing ) * ( this.group.size() - 1) ;
}
for ( var i=0; i<this.group.size(); i++) {
// Find coords of each letters (radians : angle*(Math.PI / 180)
if ( this.opts.reverse ) {
curAngle = (-i * parseInt( this.opts.spacing, 10 )) + align;
angleRadians = curAngle * (Math.PI / 180);
this.group.item(i).set( 'top', (Math.cos( angleRadians ) * this.opts.radius) );
this.group.item(i).set( 'left', (-Math.sin( angleRadians ) * this.opts.radius) );
} else {
curAngle = (i * parseInt( this.opts.spacing, 10)) - align;
angleRadians = curAngle * (Math.PI / 180);
this.group.item(i).set( 'top', (-Math.cos( angleRadians ) * this.opts.radius) );
this.group.item(i).set( 'left', (Math.sin( angleRadians ) * this.opts.radius) ) ;
}
this.group.item(i).setAngle( curAngle );
}
// Update group coords
this.group._calcBounds();
this.group._updateObjectsCoords();
this.group.top = this.opts.top;
this.group.left = this.opts.left;
this.group.saveCoords();
this.canvas.renderAll();
};
/**
* Default options
*/
CurvedText.defaults = {
top: 0,
left: 0,
scaleX: 1,
scaleY: 1,
angle: 0,
spacing: 20,
radius: 50,
text: 'Curved text',
align: 'center',
reverse: false,
fontSize: 20,
fontWeight: 'normal',
selectable: true
};
return CurvedText;
})();
$(document).ready(function(){
canvas = new fabric.Canvas('c');
Example = new CurvedText( canvas, {angle:50} );
Example.center();
$('.radius, .spacing, .align, .fontSize').change(function(){
Example.set( $(this).attr('class'), $(this).val() ) ;
});
$('.reverse').change(function(){
Example.set( 'reverse', ( $(this).val() == 'true' ) ) ;
});
$('.text').keyup(function(){
Example.setText( $(this).val() ) ;
});
});
});//]]>
</script>
</head>
<body>
<canvas id="c" width="400" height="200"></canvas>
<br>
<input type="text" class="text" value="Curved text"><br>
Rayon : <input type="range" min="0" max="100" value="50" class="radius" /><br>
Espacement : <input type="range" min="5" max="40" value="20" class="spacing" /><br>
inverser le texte : <label><input type="radio" name="reverse" class="reverse" value="true" /> Oui</label> <label><input type="radio" name="reverse" class="reverse" value="false" checked="checked" /> Non</label><br />
Alignement : <label><input type="radio" name="align" class="align" value="left" /> Gauche</label> <label><input type="radio" name="align" class="align" value="center" checked="checked" /> Centr�</label> <label><input type="radio" name="align" class="align" value="right" /> Droite</label><br >
Taille du texte : <input type="range" min="3" max="100" value="20" class="fontSize" /><br>
</body>
</html>
Related
Update: JSFiddle: https://jsfiddle.net/Qanary/915fg6ka/
I am trying to make my curveText function work (see bottom of this post). It normally works with fabric.js 1.2.0 however when I updated to fabric.js 1.7.9, the curving function locates the text in wrong positions when below two actions executed sequentially.
ACTIONS : - ISSUE 1
-text group scale is changed (I mean dragging the corner points by mouse to change size).
-setText called
fabric js 1.2.0:
fabric js 1.7.9
I debugged it and the reason for that is _updateObjectsCoords in fabricjs because when I removed it from the code and 2 actions I listed above works fine.
ISSUE 2:
But this time I have faced below problem which is group items are not correctly located when adding the text to canvas for the first time.
with _updateObjectsCoords
without _updateObjectsCoords
Here My Function:
var CurvedText = (function() {
function CurvedText( canvas, options ){
this.opts = options || {};
for ( var prop in CurvedText.defaults ) {
if (prop in this.opts) { continue; }
this.opts[prop] = CurvedText.defaults[prop];
}
this.canvas = canvas;
this.group = new fabric.Group([], {selectable: this.opts.selectable,radiusVal:this.opts.radius,spacingVal:this.opts.spacing,textFliping:this.opts.reverse});
this.canvas.add( this.group ) ;
this.canvas.centerObject( this.group );
this.setText( this.opts.text );
this.canvas.setActiveObject( this.group );
this.canvas.getActiveObject().setCoords();
}
CurvedText.prototype.setObj = function(obj)
{
this.group=obj;
};
CurvedText.prototype.setText = function( newText ) {
this.opts.top=this.group.top;
this.opts.left=this.group.left;
while ( newText.length !== 0 && this.group.size() > newText.length ) {
this.group.remove( this.group.item( this.group.size()-1 ) );
}
for ( var i=0; i<newText.length; i++ ){
if ( this.group.item(i) === undefined ){
var letter = new fabric.Text(newText[i], {
selectable: true
});
this.group.add( letter );
}
else{
this.group.item(i).text = newText[i];
}
}
this.opts.text = newText;
this._setFontStyles();
this._render();
};
CurvedText.prototype._setFontStyles = function() {
for ( var i=0; i<this.group.size(); i++ ){
if( this.opts.textStyleName )
{
if( this.opts.textStyleName === 'fontFamily' )
{
this.group.item(i).setFontFamily( this.opts.fontFamily );
}
if( this.opts.textStyleName === 'fontColor' )
{
this.group.item(i).setFill( this.opts.fontColor );
}
}
else
{
this.group.item(i).setFontFamily( this.opts.fontFamily );
this.group.item(i).setFill( this.opts.fontColor );
}
this.group.item(i).setFontSize( this.opts.fontSize );
this.group.item(i).fontWeight = this.opts.fontWeight ;
}
};
CurvedText.prototype._render = function() {
var curAngle=0,angleRadians=0, align=0;
// Object may have been moved with drag&drop
if ( this.group.hasMoved() ) {
this.opts.top = this.group.top;
this.opts.left = this.group.left;
}
this.opts.angle = this.group.getAngle();
this.opts.scaleX = this.group.scaleX;
this.opts.scaleY = this.group.scaleY;
this.opts.radius = this.group.radiusVal;
this.opts.spacing = this.group.spacingVal;
this.opts.reverse = this.group.textFliping;
// Text align
if ( this.opts.align === 'center' ) {
align = ( this.opts.spacing / 2) * ( this.group.size() - 1) ;
} else if ( this.opts.align === 'right' ) {
align = ( this.opts.spacing ) * ( this.group.size() - 1) ;
}
for ( var i=0; i<this.group.size(); i++) {
// Find coords of each letters (radians : angle*(Math.PI / 180)
if ( this.opts.reverse ) {
curAngle = (-i * parseInt( this.opts.spacing, 10 )) + align;
angleRadians = curAngle * (Math.PI / 180);
this.group.item(i).setAngle( curAngle );
this.group.item(i).set( 'top', (Math.cos( angleRadians ) * this.opts.radius) );
this.group.item(i).set( 'left', (-Math.sin( angleRadians ) * this.opts.radius) );
} else {
curAngle = (i * parseInt( this.opts.spacing, 10)) - align;
angleRadians = curAngle * (Math.PI / 180);
this.group.item(i).setAngle( curAngle );
this.group.item(i).set( 'top', (-Math.cos( angleRadians ) * this.opts.radius) );
this.group.item(i).set( 'left', (Math.sin( angleRadians ) * this.opts.radius) ) ;
}
}
// Update group coords
this.group._calcBounds();
this.group._updateObjectsCoords();
this.group.top = this.opts.top;
this.group.left = this.opts.left;
this.group.saveCoords();
this.canvas.renderAll();
};
CurvedText.defaults = {
top: 0,
left: 0,
scaleX: 1,
scaleY: 1,
angle: 0,
spacing:0,
radius:0,
text: '',
align: 'center',
reverse:'',
fontSize:16,
fontWeight: 'normal',
selectable: true,
fontFamily:'',
fontColor:'black',
textStyleName:''
};
return CurvedText;
})();
This should do it, if I understood you correctly:
Just a small tweak to your updateText() function:
function updateText() {
var original = canvas.getActiveObject();
canvas.remove(original);
setText();
canvas.getActiveObject().set({
angle: original.angle,
top: original.top,
left: original.left,
scaleX: original.scaleX,
scaleY: original.scaleY
}).setCoords();
canvas.renderAll();
}
And finally, here's your all important JSFiddle updated, https://jsfiddle.net/rekrah/pkj82n4b/.
Update (v2)
- since you did plead in your bounty to make your function work, ;-).
Change this line:
this.group = new fabric.Group([], {selectable: this.opts.selectable,name:'arc',radiusVal:this.opts.radius,spacingVal:this.opts.spacing,textFliping:this.opts.reverse,itemName:'text'});
To this:
this.group = new fabric.Group([], {selectable: this.opts.selectable,name:'arc',radiusVal:this.opts.radius,spacingVal:this.opts.spacing,textFliping:this.opts.reverse,itemName:'text',originX:'center',originY:'center'});
And to get it a little more esthetically pleasing you might want to...
Change this line: canvas = new fabric.Canvas('c',);
To this: canvas = new fabric.Canvas('c',{centeredScaling: true});
And here's your original Plunker updated again, https://jsfiddle.net/rekrah/c7cjzkfd/.
This leaves your updateText() function as you had it.
Let me know if you have any other questions. Always happy to help!
You can use this:https://github.com/EffEPi/fabric.curvedText you can see the demo
I am trying to make a dynamic pie chart, which changes on change of slider.
I have setup everything But i'am not able to introduce states in it as I am new to react. I just want that when someone slides slider, the pie chart also changes according to value of slider. Can anyone help me?
<!DOCTYPE html>
<html>
<head>
<title>React Example without Babel </title>
<script src="https://npmcdn.com/react#15.3.1/dist/react.min.js"></script>
<script src="https://npmcdn.com/react-dom#15.3.1/dist/react-dom.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.14.0-alpha1/JSXTransformer.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.4.2/react-with-addons.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/1.0.2/Chart.min.js"></script>
<link href="http://getbootstrap.com/dist/css/bootstrap.css" rel="stylesheet">
<style>
.pie{
fill:red;
}
</style>
</head>
<body>
<div class="container">
<div id="app"></div>
<div class="col-lg-5" id="slider"></div>
<div class="col-lg-6" id="pie_chart"></div>
</div>
<script type="text/jsx">
class Header extends React.Component{
render(){
return (<div><h1 className='page-header'>{this.props.text}</h1></div>);
}
}
ReactDOM.render(<Header text='Dynamic Pie Chart'/>,document.getElementById('app'));
class Slider extends React.Component{
render(){
return (<div><input type='range' min='1' max='100' /></div>);
}
}
ReactDOM.render(<Slider />,document.getElementById('slider'));
var PropTypes = React.PropTypes;
var PieChart = React.createClass({
displayName: 'PieChart',
propTypes: {
className: PropTypes.string,
size: PropTypes.number,
slices: PropTypes.arrayOf(PropTypes.shape({
color: PropTypes.string.isRequired, // hex color
value: PropTypes.number.isRequired })).isRequired },
getDefaultProps: function getDefaultProps() {
return {
size: 200 };
},
_renderPaths: function _renderPaths() {
var radCircumference = Math.PI * 2;
var center = this.props.size / 2;
var radius = center - 1; // padding to prevent clipping
var total = this.props.slices.reduce(function (totalValue, slice) {
return totalValue + slice.value;
}, 0);
var radSegment = 0;
var lastX = radius;
var lastY = 0;
return this.props.slices.map(function (slice, index) {
var color = slice.color;
var value = slice.value;
// Should we just draw a circle?
if (value === total) {
return React.createElement('circle', {
r: radius,
cx: radius,
cy: radius,
fill: color,
key: index
});
}
if (value === 0) {
return;
}
var valuePercentage = value / total;
// Should the arc go the long way round?
var longArc = valuePercentage <= 0.5 ? 0 : 1;
radSegment += valuePercentage * radCircumference;
var nextX = Math.cos(radSegment) * radius;
var nextY = Math.sin(radSegment) * radius;
// d is a string that describes the path of the slice.
// The weirdly placed minus signs [eg, (-(lastY))] are due to the fact
// that our calculations are for a graph with positive Y values going up,
// but on the screen positive Y values go down.
var d = ['M ' + center + ',' + center, 'l ' + lastX + ',' + -lastY, 'a' + radius + ',' + radius, '0', '' + longArc + ',0', '' + (nextX - lastX) + ',' + -(nextY - lastY), 'z'].join(' ');
lastX = nextX;
lastY = nextY;
return React.createElement('path', { d: d, fill: color, key: index });
});
},
/**
* #return {Object}
*/
render: function render() {
var size = this.props.size;
var center = size / 2;
return React.createElement(
'svg',
{ viewBox: '0 0 ' + size + ' ' + size },
React.createElement(
'g',
{ transform: 'rotate(-90 ' + center + ' ' + center + ')' },
this._renderPaths()
)
);
}
});
var slices = [
{ color: '#468966', value: 180 },
{ color: '#FFF0A5', value: 180 },
];
ReactDOM.render(<PieChart slices={slices} />, document.getElementById('pie_chart'));
</script>
</body>
</html>
Hi Please check the code its working now. You have to pass your slide change value to the state. I have changed few code. Please check.
<!DOCTYPE html>
<html>
<head>
<title>React Example without Babel </title>
<script src="https://npmcdn.com/react#15.3.1/dist/react.min.js"></script>
<script src="https://npmcdn.com/react-dom#15.3.1/dist/react-dom.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.14.0-alpha1/JSXTransformer.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.4.2/react-with-addons.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/1.0.2/Chart.min.js"></script>
<link href="http://getbootstrap.com/dist/css/bootstrap.css" rel="stylesheet">
<style>
.pie{
fill:red;
}
</style>
</head>
<body>
<div class="container">
<div id="app"></div>
<div class="col-lg-5" id="slider"></div>
<div class="col-lg-6" id="pie_chart"></div>
</div>
<script type="text/jsx">
class Header extends React.Component{
render(){
return (<div><h1 className='page-header'>{this.props.text}</h1></div>);
}
}
ReactDOM.render(<Header text='Dynamic Pie Chart'/>,document.getElementById('app'));
class Slider extends React.Component{
render(){
return (<div><input type='range' min='1' max='100' onChange = {this.props.sliderEvent} /></div>);
}
}
var PropTypes = React.PropTypes;
var PieChart = React.createClass({
displayName: 'PieChart',
propTypes: {
className: PropTypes.string,
size: PropTypes.number,
slices: PropTypes.arrayOf(PropTypes.shape({
color: PropTypes.string.isRequired, // hex color
value: PropTypes.number.isRequired })).isRequired },
getDefaultProps: function getDefaultProps() {
return {
size: 200 };
},
_renderPaths: function _renderPaths() {
var radCircumference = Math.PI * 2;
var center = this.props.size / 2;
var radius = center - 1; // padding to prevent clipping
var total = this.props.slices.reduce(function (totalValue, slice) {
return totalValue + slice.value;
}, 0);
var radSegment = 0;
var lastX = radius;
var lastY = 0;
return this.props.slices.map(function (slice, index) {
var color = slice.color;
var value = slice.value;
// Should we just draw a circle?
if (value === total) {
return React.createElement('circle', {
r: radius,
cx: radius,
cy: radius,
fill: color,
key: index
});
}
if (value === 0) {
return;
}
var valuePercentage = value / total;
// Should the arc go the long way round?
var longArc = valuePercentage <= 0.5 ? 0 : 1;
radSegment += valuePercentage * radCircumference;
var nextX = Math.cos(radSegment) * radius;
var nextY = Math.sin(radSegment) * radius;
// d is a string that describes the path of the slice.
// The weirdly placed minus signs [eg, (-(lastY))] are due to the fact
// that our calculations are for a graph with positive Y values going up,
// but on the screen positive Y values go down.
var d = ['M ' + center + ',' + center, 'l ' + lastX + ',' + -lastY, 'a' + radius + ',' + radius, '0', '' + longArc + ',0', '' + (nextX - lastX) + ',' + -(nextY - lastY), 'z'].join(' ');
lastX = nextX;
lastY = nextY;
return React.createElement('path', { d: d, fill: color, key: index });
});
},
/**
* #return {Object}
*/
render: function render() {
var size = this.props.size;
var center = size / 2;
return React.createElement(
'svg',
{ viewBox: '0 0 ' + size + ' ' + size },
React.createElement(
'g',
{ transform: 'rotate(-90 ' + center + ' ' + center + ')' },
this._renderPaths()
)
);
}
});
class App extends React.Component{
constructor(props){
super(props);
this.state = {
slices : [
{ color: '#468966', value: 180 },
{ color: '#FFF0A5', value: 180 },
]
};
//this.handleSliderEvent = this.bind.handleSliderEvent(this);
}
handleSliderEvent(e){
var slices1 = (360 * e.target.value)/100;
var slices2 = 360 - slices1;
var array1 = [
{ color: '#468966', value: slices1 },
{ color: '#FFF0A5', value: slices2 }
];
console.log(array1)
this.setState({slices: array1});
}
render(){
return(
<div>
<Slider sliderEvent = {this.handleSliderEvent.bind(this)}/>
<PieChart slices = {this.state.slices} />
</div>
)
}
}
ReactDOM.render(<App/>, document.getElementById('pie_chart'));
</script>
</body>
</html>
Go through the this fiddle as well which has working version of your code.
https://jsfiddle.net/oyqzms4c/
Hi Please check the below code. It should work.
<!DOCTYPE html>
<html>
<head>
<script src="https://npmcdn.com/react#15.3.1/dist/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.16/d3.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.24/browser.js"></script>
<script src="https://unpkg.com/react#15.0.1/dist/react-with-addons.js"></script>
<script src="https://unpkg.com/react-dom#15.0.1/dist/react-dom.js"></script>
<script src="https://npmcdn.com/rd3#0.6.3/build/public/js/react-d3.js"></script>
<link href="http://getbootstrap.com/dist/css/bootstrap.css" rel="stylesheet">
</head>
<body>
<div class="container">
<h1 class="page-header">Dynamic Pie Chart</h1>
<div id="slider" class="col-lg-6"></div>
<div id="container" class="col-lg-6">
</div>
</div>
</div>
</body>
<script type="text/babel">
class Chart extends React.Component{
render() {
var PieChart = rd3.PieChart;
//var pieData = [ {label: "First", value: 50}, {label: "Second", value: 50 }];
return (
<PieChart
data={this.props.data}
width={450}
height={400}
radius={110}
sectorBorderColor="white"
/>
)}
}
class Slider extends React.Component{
render(){
return (<div><input type='range' min='0' max='100' onChange = {this.props.sliderEvent} /></div>);
}
}
class App extends React.Component{
constructor(props){
super(props);
this.state = {
pieData : [
{label: "First", value: 50}, {label: "Second", value: 500 }
]
};
}
handleSliderEvent(e){
var slices1 = (360 * e.target.value)/100;
var slices2 = 360 - slices1;
var array1 = [
{ label: "First", value: slices1 },
{ label: "Second", value: slices2 }
];
this.setState({pieData: array1},function(){
console.log(this.state);
});
}
render(){
return(<div className="row">
<Slider sliderEvent = {this.handleSliderEvent.bind(this)}/>
<div className='col-lg-6'>
<Chart data = {this.state.pieData} />
</div>
</div>)
}
}
ReactDOM.render(<App/>, document.getElementById('container'));
</script>
</html>
When you are passing the state to your component it will be available in component as props. So you have to use that props.
I'm a beginner beginner. I can get the behavior that I want to occur, but instead of occurring in two separate SVGs, all the behavior is occurring in 'svg2' although I have selected the respective ids for 'svg1' and 'svg2' (or at least I think I did)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<script src="https://code.jquery.com/jquery-3.0.0.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/raphael/2.2.0/raphael-min.js"></script>
<script src="logic.js"></script>
<title>Forms and Concentric Circles</title>
</head>
<body>
<h1>Forms and Concentric Circles</h1>
<div id="svg1"></div>
<div class="form">Add how many?
<input type="text" id="howmany" />
<button id="more">Add More</button></div>
<div id="svg2"></div>
<div class="form">
<button id="another">Add Another</button>
</div>
</body>
</html>
var paper;
disappear = function() {
this.remove();
}
spin = function(r) {
angle = Math.random()*1440 - 720;
initial = { 'transform': 'r0' }
final = { 'transform': 'r' + angle}
r.attr(initial);
r.animate(final, 2000);
}
addMore = function() {
rectNum = $('#howmany').val();
for (step = 0; step < rectNum; step += 1) {
x = Math.random() * 180;
y = Math.random() * 180;
r = paper.rect(x, y, 20, 20);
filled = {
'fill': '#ddf'
}
r.attr(filled);
r.click(disappear);
spin(r);
}
}
radius = 10
morecircles = function() {
paper.circle(100, 100, radius);
radius = radius + 10;
}
setup = function() {
paper = Raphael('svg1', 200, 200);
$('#more').click(addMore);
paper = Raphael('svg2', 200, 200);
$('#another').click(morecircles);
}
$(document).ready(setup);
change the name for the second svg for example
paper2.circle
and in your setup function it should be
paper2.Raphael('svg2',200,200)
I have the following markup:
I am using Piklor, a cooler picker https://github.com/jillix/piklor.js/
It is initialised by:
header = pk.getElm(".selected-icon p")
and the colour attributes are assigned here:
header.style.color = col;
However, the above doesn't work. Am I targeting the p tag right? The class of the p tag changes pragmatically in my scrip, so I can't really use the class name and can only refer to it by the parent element.
If I target ".selected-icon" (without the p tag) and with a backgroundColor, e.g. header.style.backgroundColor = col; it seems to work, but not the colour of the p tag.
(function (root) {
/**
* Piklor
* Creates a new `Piklor` instance.
*
* #name Piklor
* #function
* #param {String|Element} sel The element where the color picker will live.
* #param {Array} colors An array of strings representing colors.
* #param {Object} options An object containing the following fields:
*
* - `open` (String|Element): The HTML element or query selector which will open the picker.
* - `openEvent` (String): The open event (default: `"click"`).
* - `style` (Object): Some style options:
* - `display` (String): The display value when the picker is opened (default: `"block"`).
* - `template` (String): The color item template. The `{color}` snippet will be replaced
* with the color value (default: `"<div data-col=\"{color}\" style=\"background-color: {color}\"></div>"`).
* - `autoclose` (Boolean): If `false`, the color picker will not be hided by default (default: `true`).
* - `closeOnBlur` (Boolean): If `true`, the color picker will be closed when clicked outside of it (default: `false`).
*
* #return {Piklor} The `Piklor` instance.
*/
function Piklor(sel, colors, options) {
var self = this;
options = options || {};
options.open = self.getElm(options.open);
options.openEvent = options.openEvent || "click";
options.style = Object(options.style);
options.style.display = options.style.display || "block";
options.closeOnBlur = options.closeOnBlur || false;
options.template = options.template || "<div data-col=\"{color}\" style=\"background-color: {color}\"></div>";
self.elm = self.getElm(sel);
self.cbs = [];
self.isOpen = true;
self.colors = colors;
self.options = options;
self.render();
// Handle the open element and event.
if (options.open) {
options.open.addEventListener(options.openEvent, function (ev) {
self.isOpen ? self.close() : self.open();
});
}
// Click on colors
self.elm.addEventListener("click", function (ev) {
var col = ev.target.getAttribute("data-col");
if (!col) { return; }
self.set(col);
self.close();
});
if (options.closeOnBlur) {
window.addEventListener("click", function (ev) {
// check if we didn't click 'open' and 'color pallete' elements
if (ev.target != options.open && ev.target != self.elm && self.isOpen) {
self.close();
}
});
}
if (options.autoclose !== false) {
self.close();
}
}
/**
* getElm
* Finds the HTML element.
*
* #name getElm
* #function
* #param {String|Element} el The HTML element or query selector.
* #return {HTMLElement} The selected HTML element.
*/
Piklor.prototype.getElm = function (el) {
if (typeof el === "string") {
return document.querySelector(el);
}
return el;
};
/**
* render
* Renders the colors.
*
* #name render
* #function
*/
Piklor.prototype.render = function () {
var self = this
, html = ""
;
self.colors.forEach(function (c) {
html += self.options.template.replace(/\{color\}/g, c);
});
self.elm.innerHTML = html;
};
/**
* close
* Closes the color picker.
*
* #name close
* #function
*/
Piklor.prototype.close = function () {
this.elm.style.display = "none";
this.isOpen = false;
};
/**
* open
* Opens the color picker.
*
* #name open
* #function
*/
Piklor.prototype.open = function () {
this.elm.style.display = this.options.style.display;
this.isOpen = true;
};
/**
* colorChosen
* Adds a new callback in the colorChosen callback buffer.
*
* #name colorChosen
* #function
* #param {Function} cb The callback function called with the selected color.
*/
Piklor.prototype.colorChosen = function (cb) {
this.cbs.push(cb);
};
/**
* set
* Sets the color picker color.
*
* #name set
* #function
* #param {String} c The color to set.
* #param {Boolean} p If `false`, the `colorChosen` callbacks will not be called.
*/
Piklor.prototype.set = function (c, p) {
var self = this;
self.color = c;
if (p === false) { return; }
self.cbs.forEach(function (cb) {
cb.call(self, c);
});
};
root.Piklor = Piklor;
})(this);
window.addEventListener("load", function () {
var pk = new Piklor(".color-picker", [
"#1abc9c"
, "#2ecc71"
, "#3498db"
, "#9b59b6"
, "#34495e"
, "#16a085"
, "#27ae60"
, "#2980b9"
, "#8e44ad"
, "#2c3e50"
, "#f1c40f"
, "#e67e22"
, "#e74c3c"
, "#ecf0f1"
, "#95a5a6"
, "#f39c12"
, "#d35400"
, "#c0392b"
, "#bdc3c7"
, "#7f8c8d"
], {
open: ".picker-wrapper .btn"
})
, wrapperEl = pk.getElm(".picker-wrapper")
, header = pk.getElm(".selected-icon p")
, footer = pk.getElm("footer")
;
pk.colorChosen(function (col) {
wrapperEl.style.backgroundColor = col;
header.style.backgroundColor = col;
footer.style.backgroundColor = col;
});
});
/* picker */
.color-picker {
background: rgba(255, 255, 255, 0.75);
padding: 10px;
border: 1px solid rgba(203, 203, 203, 0.6);
border-radius: 2px;
}
.color-picker > div {
width: 40px;
display: inline-block;
height: 40px;
margin: 5px;
border-radius: 100%;
opacity: 0.7;
}
.picker-wrapper {
padding: 20px;
}
.color-picker > div:hover {
opacity: 1;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.0/jquery.min.js"></script>
<span class="selected-icon"><p class="icon-eight">Hello</i></span>
<div class="picker-wrapper">
<button class="btn btn-default">Select color</button>
<div class="color-picker">
</div>
</div>
Okay. If that is the case, your issue is the p tag is not closed.
<span class="selected-icon"><p class="icon-eight">Hello</i></span>
You have an "i" tag trying to close the leading "p" tag. Change that and you should be good to go.
Also change
header.style.backgroundColor = col;
To
header.style.color = col;
To achieve the desired result.
I have this jquery plugin that zooms in on photos, but I would like to animate the zoom so it just doesn't zoom in, but so that there is like an animated effect on the zoom. Is this possible?
Here is the page I have the plugin set up on right now. http://www.buildinfocus.com/clients/gallery_detail.php?title=1&mapid=239
Maybe something like this http://api.jquery.com/animate/
Below is the code I have for plugin
(function($){
$.fn.iviewer = function(o)
{
return this.each(function()
{
$(this).data('viewer', new $iv(this,o));
});
}
var defaults = {
/**
* start zoom value for image, not used now
* may be equal to "fit" to fit image into container or scale in %
**/
zoom: "fit",
/**
* base value to scale image
**/
zoom_base: 100,
/**
* maximum zoom
**/
zoom_max: 800,
/**
* minimum zoom
**/
zoom_min: 25,
/**
* base of rate multiplier.
* zoom is calculated by formula: zoom_base * zoom_delta^rate
**/
zoom_delta: 1.4,
/**
* if true plugin doesn't add its own controls
**/
ui_disabled: false,
/**
* if false, plugin doesn't bind resize event on window and this must
* be handled manually
**/
update_on_resize: true,
/**
* event is triggered when zoom value is changed
* #param int new zoom value
* #return boolean if false zoom action is aborted
**/
onZoom: null,
/**
* callback is fired after plugin setup
**/
initCallback: null,
/**
* event is fired on drag begin
* #param object coords mouse coordinates on the image
* #return boolean if false is returned, drag action is aborted
**/
onStartDrag: null,
/**
* event is fired on drag action
* #param object coords mouse coordinates on the image
**/
onDrag: null,
/**
* event is fired when mouse moves over image
* #param object coords mouse coordinates on the image
**/
onMouseMove: null,
/**
* mouse click event
* #param object coords mouse coordinates on the image
**/
onClick: null,
/**
* event is fired when image starts to load
*/
onStartLoad: null,
/**
* event is fired, when image is loaded and initially positioned
*/
onFinishLoad: null
};
$.iviewer = function(e,o)
{
var me = this;
/* object containing actual information about image
* #img_object.object - jquery img object
* #img_object.orig_{width|height} - original dimensions
* #img_object.display_{width|height} - actual dimensions
*/
this.img_object = {};
this.zoom_object = {}; //object to show zoom status
this.image_loaded = false;
//drag variables
this.dx = 0;
this.dy = 0;
this.dragged = false;
this.settings = $.extend({}, defaults, o || {});
this.current_zoom = this.settings.zoom;
if(this.settings.src === null){
return;
}
this.container = $(e);
this.update_container_info();
//init container
this.container.css("overflow","hidden");
if(this.settings.update_on_resize == true)
{
$(window).resize(function()
{
me.update_container_info();
});
}
this.img_object.x = 0;
this.img_object.y = 0;
//init object
this.img_object.object = $("<img>").
css({ position: "absolute", top :"0px", left: "0px"}). //this is needed, because chromium sets them auto otherwise
//bind mouse events
mousedown(function(e){ return me.drag_start(e); }).
mousemove(function(e){return me.drag(e)}).
mouseup(function(e){return me.drag_end(e)}).
click(function(e){return me.click(e)}).
mouseleave(function(e){return me.drag_end(e)}).
mousewheel(function(ev, delta)
{
//this event is there instead of containing div, because
//at opera it triggers many times on div
var zoom = (delta > 0)?1:-1;
me.zoom_by(zoom);
return false;
});
this.img_object.object.prependTo(me.container);
this.loadImage(this.settings.src);
if(!this.settings.ui_disabled)
{
this.createui();
}
if(this.settings.initCallback)
{
this.settings.initCallback.call(this);
}
}
var $iv = $.iviewer;
$iv.fn = $iv.prototype = {
iviewer : "0.4.2"
}
$iv.fn.extend = $iv.extend = $.extend;
$iv.fn.extend({
loadImage: function(src)
{
this.current_zoom = this.settings.zoom;
this.image_loaded = false;
var me = this;
if(this.settings.onStartLoad)
{
this.settings.onStartLoad.call(this);
}
this.img_object.object.unbind('load').
removeAttr("src").
removeAttr("width").
removeAttr("height").
css({ top: 0, left: 0 }).
load(function(){
me.image_loaded = true;
me.img_object.display_width = me.img_object.orig_width = this.width;
me.img_object.display_height = me.img_object.orig_height = this.height;
if(!me.container.hasClass("iviewer_cursor")){
me.container.addClass("iviewer_cursor");
}
if(me.settings.zoom == "fit"){
me.fit();
}
else {
me.set_zoom(me.settings.zoom);
}
if(me.settings.onFinishLoad)
{
me.settings.onFinishLoad.call(me);
}
//src attribute is after setting load event, or it won't work
}).attr("src",src);
},
/**
* fits image in the container
**/
fit: function()
{
var aspect_ratio = this.img_object.orig_width / this.img_object.orig_height;
var window_ratio = this.settings.width / this.settings.height;
var choose_left = (aspect_ratio > window_ratio);
var new_zoom = 0;
if(choose_left){
new_zoom = this.settings.width / this.img_object.orig_width * 100;
}
else {
new_zoom = this.settings.height / this.img_object.orig_height * 100;
}
this.set_zoom(new_zoom);
},
/**
* center image in container
**/
center: function()
{
this.setCoords(-Math.round((this.img_object.display_height - this.settings.height)/2),
-Math.round((this.img_object.display_width - this.settings.width)/2));
},
/**
* move a point in container to the center of display area
* #param x a point in container
* #param y a point in container
**/
moveTo: function(x, y)
{
var dx = x-Math.round(this.settings.width/2);
var dy = y-Math.round(this.settings.height/2);
var new_x = this.img_object.x - this.dx;
var new_y = this.img_object.y - this.dy;
this.setCoords(new_x, new_y);
},
/**
* set coordinates of upper left corner of image object
**/
setCoords: function(x,y)
{
//do nothing while image is being loaded
if(!this.image_loaded)
{
return;
}
//check new coordinates to be correct (to be in rect)
if(y > 0){
y = 0;
}
if(x > 0){
x = 0;
}
if(y + this.img_object.display_height < this.settings.height){
y = this.settings.height - this.img_object.display_height;
}
if(x + this.img_object.display_width < this.settings.width){
x = this.settings.width - this.img_object.display_width;
}
if(this.img_object.display_width <= this.settings.width){
x = -(this.img_object.display_width - this.settings.width)/2;
}
if(this.img_object.display_height <= this.settings.height){
y = -(this.img_object.display_height - this.settings.height)/2;
}
this.img_object.x = x;
this.img_object.y = y;
this.img_object.object.css("top",y + "px")
.css("left",x + "px");
},
/**
* convert coordinates on the container to the coordinates on the image (in original size)
*
* #return object with fields x,y according to coordinates or false
* if initial coords are not inside image
**/
containerToImage : function (x,y)
{
if(x < this.img_object.x || y < this.img_object.y ||
x > this.img_object.x + this.img_object.display_width ||
y > this.img_object.y + this.img_object.display_height)
{
return false;
}
return { x : $iv.descaleValue(x - this.img_object.x, this.current_zoom),
y : $iv.descaleValue(y - this.img_object.y, this.current_zoom)
};
},
/**
* convert coordinates on the image (in original size) to the coordinates on the container
*
* #return object with fields x,y according to coordinates or false
* if initial coords are not inside image
**/
imageToContainer : function (x,y)
{
if(x > this.img_object.orig_width || y > this.img_object.orig_height)
{
return false;
}
return { x : this.img_object.x + $iv.scaleValue(x, this.current_zoom),
y : this.img_object.y + $iv.scaleValue(y, this.current_zoom)
};
},
/**
* get mouse coordinates on the image
* #param e - object containing pageX and pageY fields, e.g. mouse event object
*
* #return object with fields x,y according to coordinates or false
* if initial coords are not inside image
**/
getMouseCoords : function(e)
{
var img_offset = this.img_object.object.offset();
return { x : $iv.descaleValue(e.pageX - img_offset.left, this.current_zoom),
y : $iv.descaleValue(e.pageY - img_offset.top, this.current_zoom)
};
},
/**
* set image scale to the new_zoom
* #param new_zoom image scale in %
**/
set_zoom: function(new_zoom)
{
if(this.settings.onZoom && this.settings.onZoom.call(this, new_zoom) == false)
{
return;
}
//do nothing while image is being loaded
if(!this.image_loaded)
{
return;
}
if(new_zoom < this.settings.zoom_min)
{
new_zoom = this.settings.zoom_min;
}
else if(new_zoom > this.settings.zoom_max)
{
new_zoom = this.settings.zoom_max;
}
/* we fake these values to make fit zoom properly work */
if(this.current_zoom == "fit")
{
var old_x = Math.round(this.settings.width/2 + this.img_object.orig_width/2);
var old_y = Math.round(this.settings.height/2 + this.img_object.orig_height/2);
this.current_zoom = 100;
}
else {
var old_x = -parseInt(this.img_object.object.css("left"),10) +
Math.round(this.settings.width/2);
var old_y = -parseInt(this.img_object.object.css("top"),10) +
Math.round(this.settings.height/2);
}
var new_width = $iv.scaleValue(this.img_object.orig_width, new_zoom);
var new_height = $iv.scaleValue(this.img_object.orig_height, new_zoom);
var new_x = $iv.scaleValue( $iv.descaleValue(old_x, this.current_zoom), new_zoom);
var new_y = $iv.scaleValue( $iv.descaleValue(old_y, this.current_zoom), new_zoom);
new_x = this.settings.width/2 - new_x;
new_y = this.settings.height/2 - new_y;
this.img_object.object.attr("width",new_width)
.attr("height",new_height);
this.img_object.display_width = new_width;
this.img_object.display_height = new_height;
this.setCoords(new_x, new_y);
this.current_zoom = new_zoom;
$.isFunction( this.settings.onAfterZoom ) && this.settings.onAfterZoom.call( this, new_zoom );
this.update_status();
},
/**
* changes zoom scale by delta
* zoom is calculated by formula: zoom_base * zoom_delta^rate
* #param Integer delta number to add to the current multiplier rate number
**/
zoom_by: function(delta)
{
var closest_rate = this.find_closest_zoom_rate(this.current_zoom);
var next_rate = closest_rate + delta;
var next_zoom = this.settings.zoom_base * Math.pow(this.settings.zoom_delta, next_rate)
if(delta > 0 && next_zoom < this.current_zoom)
{
next_zoom *= this.settings.zoom_delta;
}
if(delta < 0 && next_zoom > this.current_zoom)
{
next_zoom /= this.settings.zoom_delta;
}
this.set_zoom(next_zoom);
},
/**
* finds closest multiplier rate for value
* basing on zoom_base and zoom_delta values from settings
* #param Number value zoom value to examine
**/
find_closest_zoom_rate: function(value)
{
if(value == this.settings.zoom_base)
{
return 0;
}
function div(val1,val2) { return val1 / val2 };
function mul(val1,val2) { return val1 * val2 };
var func = (value > this.settings.zoom_base)?mul:div;
var sgn = (value > this.settings.zoom_base)?1:-1;
var mltplr = this.settings.zoom_delta;
var rate = 1;
while(Math.abs(func(this.settings.zoom_base, Math.pow(mltplr,rate)) - value) >
Math.abs(func(this.settings.zoom_base, Math.pow(mltplr,rate+1)) - value))
{
rate++;
}
return sgn * rate;
},
/* update scale info in the container */
update_status: function()
{
if(!this.settings.ui_disabled)
{
var percent = Math.round(100*this.img_object.display_height/this.img_object.orig_height);
if(percent)
{
this.zoom_object.html(percent + "%");
}
}
},
update_container_info: function()
{
this.settings.height = this.container.height();
this.settings.width = this.container.width();
},
/**
* callback for handling mousdown event to start dragging image
**/
drag_start: function(e)
{
if(this.settings.onStartDrag &&
this.settings.onStartDrag.call(this,this.getMouseCoords(e)) == false)
{
return false;
}
/* start drag event*/
this.dragged = true;
this.container.addClass("iviewer_drag_cursor");
this.dx = e.pageX - this.img_object.x;
this.dy = e.pageY - this.img_object.y;
return false;
},
/**
* callback for handling mousmove event to drag image
**/
drag: function(e)
{
this.settings.onMouseMove &&
this.settings.onMouseMove.call(this,this.getMouseCoords(e));
if(this.dragged){
this.settings.onDrag &&
this.settings.onDrag.call(this,this.getMouseCoords(e));
var ltop = e.pageY -this.dy;
var lleft = e.pageX -this.dx;
this.setCoords(lleft, ltop);
return false;
}
},
/**
* callback for handling stop drag
**/
drag_end: function(e)
{
this.container.removeClass("iviewer_drag_cursor");
this.dragged=false;
},
click: function(e)
{
this.settings.onClick &&
this.settings.onClick.call(this,this.getMouseCoords(e));
},
/**
* create zoom buttons info box
**/
createui: function()
{
var me=this;
$("<div>").addClass("iviewer_zoom_in").addClass("iviewer_common").
addClass("iviewer_button").
mousedown(function(){me.zoom_by(1); return false;}).appendTo(this.container);
$("<div>").addClass("iviewer_zoom_out").addClass("iviewer_common").
addClass("iviewer_button").
mousedown(function(){me.zoom_by(- 1); return false;}).appendTo(this.container);
$("<div>").addClass("iviewer_zoom_zero").addClass("iviewer_common").
addClass("iviewer_button").
mousedown(function(){me.set_zoom(100); return false;}).appendTo(this.container);
$("<div>").addClass("iviewer_zoom_fit").addClass("iviewer_common").
addClass("iviewer_button").
mousedown(function(){me.fit(this); return false;}).appendTo(this.container);
this.zoom_object = $("<div>").addClass("iviewer_zoom_status").addClass("iviewer_common").
appendTo(this.container);
this.update_status(); //initial status update
}
});
$iv.extend({
scaleValue: function(value, toZoom)
{
return value * toZoom / 100;
},
descaleValue: function(value, fromZoom)
{
return value * 100 / fromZoom;
}
});
})(jQuery);
Try updating to the latest version, it looks to support smooth zoom transition (so you won't have to implement this yourself):
https://github.com/can3p/iviewer/blob/master/jquery.iviewer.js#L415
On line 415, the set_zoom function animates the trnasition, as opposed to the older code you pasted, which just changes the css values.
The last version of the plugin(0.5) supports smooth zoom, try it.