Click here to Skip to main content
12,763,515 members (32,072 online)
Click here to Skip to main content

Stats

63.7K views
757 downloads
59 bookmarked
Posted 23 Feb 2013

HTML5 Canvas CurvyTip

, 21 Mar 2013 MIT
CurvyTip HTML5 Canvas experiment.
function GetAngle(a,b,c){var d=100/a.segments*(b+c);return(a.endAngle-a.startAngle)*d/100+a.startAngle}function getX(a,b,c){return c+Math.cos(a*TO_RADIANS)*b}function getY(a,b,c){return c-Math.sin(a*TO_RADIANS)*b}function drawSegment(a,b){var c=a.radius,d=a.arcRadius,e=GetAngle(a,b,1),f=GetAngle(a,b,0),g=a.cX,h=a.cY/.5,i=parseInt(a.segments/2)==b,j=a.context,k=(e+f)/2,l=getX(e,c,g),m=getY(e,c,h),n=getX(e,c-d,g),o=getY(e,c-d,h),p=getX(f,c,g),q=getY(f,c,h),r=getX(f,c-d,g),s=getY(f,c-d,h),t=getX(k,c+a.ctxFactor,g),u=getY(k,c+a.ctxFactor,h),v=getX(k,c-d+a.ctxFactor,g),w=getX(k+4,c-d,g),x=getX(k-4,c-d,g),y=getY(k+4,c-d,h),z=getY(k-4,c-d,h),A=getX(k,c-d+a.ctxFactor,g),B=getY(k,c-d+a.ctxFactor,h+8),C=getY(k,c-d+a.ctxFactor,h);j.moveTo(l,m),j.quadraticCurveTo(l,m,n,o),j.moveTo(n,o),i?(j.quadraticCurveTo(n,o,x,z),j.lineTo(A,B),j.lineTo(w,y),j.quadraticCurveTo(r,s,r,s)):j.quadraticCurveTo(v,C,r,s),j.quadraticCurveTo(r,s,p,q),j.quadraticCurveTo(t,u,l,m)}function SetPosition(a){var b=a.anchor,c=10,d=getOffset(a.target),e=a.target.offsetWidth,f=a.target.offsetHeight,g=parseInt(a.segments/2),h=GetAngle(a,g,1),i=GetAngle(a,g,0),j=(h+i)/2,k=a.cY/.5;a.cX;var m=getY(j,a.radius-a.arcRadius+a.ctxFactor,k+8),n=0,o=0;switch(b){case"top":case null:default:n=d.left-a.canvas.width/2+a.target.offsetWidth/2,o=d.top-m-c;break;case"bottom":n=d.left-a.canvas.width/2+a.target.offsetWidth/2,o=d.top+f-(a.canvas.height-m)+c;break;case"left":n=d.left-c-m,o=d.top+f/2-m;break;case"right":n=d.left+e-(a.canvas.width-m)+c,o=d.top+f/2-m}setOpacity(a.canvas,1),a.canvas.setAttribute("style","display:block; left:"+n+"px; top:"+o+"px;z-index:9999")}function getOffset(a){for(var b=Object(),c=0,d=0;a;)c+=a.offsetTop,d+=a.offsetLeft,a=a.offsetParent;return b.left=d,b.top=c,b}function setOpacity(a,b){a.style.opacity=b,a.style.MozOpacity=b,a.style.KhtmlOpacity=b,a.style.filter="alpha(opacity="+100*b+")"}function fadeOut(a){var b=1,c=setInterval(function(){.1>=b&&(clearInterval(c),a.canvas.style.display="none",a.isbeingClosed=!1),setOpacity(a.canvas,b),b-=.1*b},15)}var TO_RADIANS=Math.PI/180,CurvyTip=function(a){new Image;var c=this,d=document.createElement("canvas");d.setAttribute("class","tooltip"),d.setAttribute("className","tooltip");var e=document.body;e.appendChild(d),this.canvas=d,this.canvas.width=200,this.canvas.height=200,this.context=this.canvas.getContext("2d"),this.stage=void 0,this.listening=!1,this.mousePos=null,this.mouseClick=!1,this.mouseOver=!1,this.mouseMove=!1,this.currentRegion=null,this.regionIndex=-1,this.lastRegionIndex=-1,this.mouseOverRegionIndex=-1,this.hasShadow=!0,this.target=document.getElementById(a),this.alwaysVisible=!1,this.hitSegment=-1,this.startAngle=130,this.endAngle=50,this.segments=3,this.radius=150,this.arcRadius=50,this.rotation=0,this.scale=1,this.tiles=[],this.images=[],this.currentRegionEvent={},this.anchor="top",this.isbeingClosed=!1,this.shadowColor="rgba(0,0,0,0.6)",this.backColor="rgba(0, 0, 0, 0.5)",this.mouseOverColor="rgba(128, 143, 255, 0.44)",this.width=this.canvas.width,this.height=this.canvas.height,this.cX=this.width/2,this.cY=this.height/2,this.ctxFactor=11.5*((this.startAngle-this.endAngle)/this.segments)/100,this.gradient=null,this.target.onmouseover=function(){c.isbeingClosed=!1,SetPosition(c),c.refresh()},document.addEventListener("click",function(){c.alwaysVisible||(c.isbeingClosed=!0,fadeOut(c))},!1),window.addEventListener("resize",function(){c.refresh()},!1),window.addEventListener?window.addEventListener("load",function(){c.refresh()},!1):window.attachEvent&&window.attachEvent("onload",function(){c.refresh()},!1),this.setStage(function(){(0==this.isbeingClosed&&"block"==this.canvas.style.display||this.alwaysVisible)&&(SetPosition(this),this.clearCvs(),this.context.save(),this.context.translate(this.cX,this.cY),this.context.rotate(this.rotation*TO_RADIANS),this.context.translate(-this.cX,-this.cY),this.context.scale(this.scale,this.scale),this.drawCanvas(),this.context.restore(),this.target.style.zIndex=this.canvas.style.zIndex+1)})};CurvyTip.prototype.reset=function(a){a||(a=window.event),null!=a&&this.setMousePosition(a),this.regionIndex=0,void 0!==this.stage&&this.stage(),this.mouseClick=!1,this.mouseOver=!1,this.mouseMove=!1},CurvyTip.prototype.listen=function(){var a=this;void 0!==this.stage&&this.stage(),this.canvas.addEventListener("click",function(b){a.mouseClick=!0,a.reset(b)},!1),this.canvas.addEventListener("mousemove",function(b){a.reset(b)},!1),this.canvas.addEventListener("mouseover",function(){a.mousePos=null},!1),this.canvas.addEventListener("mouseout",function(){a.mousePos=null},!1)},CurvyTip.prototype.getMousePos=function(){return this.mousePos},CurvyTip.prototype.setMousePosition=function(a){var b=a.clientX-this.getCanvasPos().left+window.pageXOffset,c=a.clientY-this.getCanvasPos().top+window.pageYOffset;this.mousePos={x:b,y:c}},CurvyTip.prototype.beginRegion=function(){this.currentRegion={},this.regionIndex++},CurvyTip.prototype.addRegionEventListener=function(a,b){var c="on"+a;this.currentRegion[c]=b},CurvyTip.prototype.closeRegion=function(){var a=this.mousePos;null!=a&&this.context.isPointInPath(a.x,a.y)?(this.lastRegionIndex!=this.regionIndex&&this.mouseOverRegionIndex!=this.lastRegionIndex&&(this.lastRegionIndex=this.regionIndex),this.mouseClick&&void 0!==this.currentRegion.onclick?(this.currentRegion.onclick(),this.mouseClick=!1):this.mouseOver||-1!=this.lastRegionIndex||this.regionIndex==this.mouseOverRegionIndex||void 0===this.currentRegion.onmouseover||(this.currentRegion.onmouseover(),this.mouseOver=!0,this.mouseOverRegionIndex=this.regionIndex)):this.regionIndex==this.lastRegionIndex&&(this.mouseOverRegionIndex=-1,this.lastRegionIndex=-1,void 0!==this.currentRegion.onmouseout&&this.currentRegion.onmouseout())},CurvyTip.prototype.getCanvasPos=function(){for(var a=this.canvas,b=0,c=0;null!=a&&"BODY"!=a.tagName;)b+=a.offsetTop,c+=a.offsetLeft,a=a.offsetParent;return{top:b,left:c}},CurvyTip.prototype.setStage=function(a){this.stage=a,this.listen()},CurvyTip.prototype.clear=function(){this.context.clearRect(0,0,this.canvas.width,this.canvas.height)},CurvyTip.prototype.refresh=function(){this.isbeingClosed||this.reset()},CurvyTip.prototype.setOptions=function(a){var b;for(b in a)this.hasOwnProperty(b)&&(this[b]=a[b],"images"==b&&this.setupImages());return this},CurvyTip.prototype.setupImages=function(){var a=this;for(this.tiles=[],x=0;this.segments>=x;x++){var b=new Image;b.src=this.images[x],this.tiles.push(b),b.onload=function(){setTimeout(function(){a.refresh()},0)}}return this},CurvyTip.prototype.addListener=function(a,b){var c="on"+a;return this.currentRegionEvent[c]=b,!1},CurvyTip.prototype.removeListener=function(a){var c="on"+a;return this.currentRegionEvent[c]=void 0,!1},CurvyTip.prototype.clearCvs=function(){this.isbeingClosed||this.context.clearRect(0,0,this.width,this.height)},CurvyTip.prototype.drawCanvas=function(){if(null==this.gradient){var a=this.context.createLinearGradient(0,0,0,this.cY/.75);a.addColorStop(0,"rgb(255, 255, 255)"),a.addColorStop(1,this.backColor),this.context.fillStyle=a}else this.context.fillStyle=this.gradient;if(this.context.lineWidth=.5,this.context.strokeStyle="black",this.hasShadow){this.context.save(),this.context.beginPath(),this.context.shadowColor=this.shadowColor,this.context.shadowBlur=5,this.context.shadowOffsetX=0,this.context.shadowOffsetY=5;for(var b=0;this.segments>b;b++)drawSegment(this,b);this.context.closePath(),this.context.fill(),this.context.restore()}for(var b=0;this.segments>b;b++){this.beginRegion(),this.context.beginPath(),drawSegment(this,b),this.context.fill(),this.context.stroke(),this.context.closePath();var c=this;this.addRegionEventListener("mouseover",function(){c.hitSegment=b,void 0!==c.currentRegionEvent.onmouseover&&c.currentRegionEvent.onmouseover(b)}),this.addRegionEventListener("click",function(){void 0!==c.currentRegionEvent.onclick&&c.currentRegionEvent.onclick(b)}),this.addRegionEventListener("mouseout",function(){c.hitSegment=-1,void 0!==c.currentRegionEvent.onmouseout&&c.currentRegionEvent.onmouseout(b)}),this.closeRegion()}for(var b=0;this.segments>b;b++){var d=GetAngle(this,b,1),e=GetAngle(this,b,0),f=this.cX,g=this.cY/.5,h=(d+e)/2,i=getX(h,this.radius-this.arcRadius/2,f),j=getY(h,this.radius-this.arcRadius/2,g);this.hitSegment==b&&(this.context.save(),this.context.beginPath(),drawSegment(this,b),this.context.fillStyle=this.mouseOverColor,this.context.fill(),this.context.closePath(),this.context.restore()),this.tiles[b]!==void 0&&(this.context.save(),this.context.shadowColor="rgb(0, 0, 0)",this.context.shadowOffsetX=0,this.context.shadowOffsetY=-1,this.context.shadowBlur=1,this.context.translate(i,j),this.context.rotate(-this.rotation*TO_RADIANS),this.context.drawImage(this.tiles[b],-(this.tiles[b].width/2),-(this.tiles[b].height/2)),this.context.restore())}};

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The MIT License

Share

About the Author

sistec
United States United States
No Biography provided

You may also be interested in...

Permalink | Advertise | Privacy | Terms of Use | Mobile
Web01 | 2.8.170217.1 | Last Updated 21 Mar 2013
Article Copyright 2013 by sistec
Everything else Copyright © CodeProject, 1999-2017
Layout: fixed | fluid