A dynamic menu I've built that can be used with either icons or text for the slider bubbles.
This one is a fun emoticon rating slider - you can drag and throw or just click to show how you feel.
A Pen by Chris Gannon on CodePen.
<div class="container"> | |
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="800px" height="600px" viewBox="0 0 800 600" text-rendering="auto"> | |
<defs> | |
<circle class="dot" fill="#FF69B4" stroke="none" stroke-width="0" stroke-miterlimit="10" cx="0" cy="300"/> | |
<g class="textGroup"> | |
<text class='label'>HI</text> | |
</g> | |
<filter id="goo"> | |
<feGaussianBlur in="SourceGraphic" stdDeviation="8" result="blur" /> | |
<feColorMatrix in="blur" mode="matrix" values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 31 -12" result="cm" /> | |
</filter> | |
<g class="speechBubbleGroup"> | |
<path class="speechBubbleStroke" fill="none" stroke-width="14" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" d=" | |
M69.361,112.063l16.377,28.99l16.562-28.94c37.277-5.125,65.195-27.13,65.195-53.494C167.496,28.456,130.766,4,85.515,4 | |
C40.275,4,4,28.456,4,58.619c0,26.291,27.361,48.249,65.361,53.448V112.063z"/> | |
<path class="speechBubbleFill" d="M69.361,109.063l16.377,28.99l16.562-28.94 | |
c37.277-5.125,65.195-27.13,65.195-53.494C167.496,25.456,130.766,1,85.515,1C40.275,1,4,25.456,4,55.619 | |
c0,26.291,27.361,48.249,65.361,53.448V109.063z"/> | |
<text class="iconLabel" x="85" y="67">WONDERFUL!</text> | |
</g> | |
<g class="popLines" fill="none" stroke="#FF69B4" stroke-width="4" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10"> | |
<line x1="107.923" y1="21.37" x2="116.935" y2="4"/> | |
<line x1="59.335" y1="24.909" x2="50.5" y2="8.057"/> | |
<line x1="21.789" y1="56.11" x2="4" y2="53.67"/> | |
<line x1="26.782" y1="98.86" x2="8.057" y2="108.34"/> | |
<line x1="65.885" y1="125.86" x2="56.43" y2="145.37"/> | |
<line x1="112.429" y1="121.342" x2="121.03" y2="142.564"/> | |
<line x1="147.535" y1="93.82" x2="168.155" y2="101.45"/> | |
<line x1="149.742" y1="49.01" x2="168.155" y2="42.56"/> | |
</g> | |
<path id="happy" d="M16,0C7.2,0,0,7.2,0,16s7.2,16,16,16s16-7.2,16-16S24.8,0,16,0z M22,8c1.1,0,2,1.3,2,3s-0.9,3-2,3s-2-1.3-2-3 | |
S20.9,8,22,8z M10,8c1.1,0,2,1.3,2,3s-0.9,3-2,3s-2-1.3-2-3S8.9,8,10,8z M16,28c-5.2,0-9.5-4.4-10-9.9c2.9,1.7,6.4,2.7,10,2.7 | |
s7.1-1,10-2.7C25.5,23.6,21.2,28,16,28L16,28z"/> | |
<path id="evil" d="M32,2c0-1.4-0.3-2.8-0.8-4c-1,2.4-3,4.3-5.5,5.3C23,1.2,19.7,0,16,0S9,1.2,6.3,3.3C3.8,2.3,1.9,0.4,0.8-2 | |
C0.3-0.8,0,0.6,0,2c0,2.3,0.8,4.4,2.1,6.1C0.8,10.4,0,13.1,0,16c0,8.8,7.2,16,16,16s16-7.2,16-16c0-2.9-0.8-5.6-2.1-7.9 | |
C31.2,6.4,32,4.3,32,2z M18,11.9c0.1-1.5,1.4-2.5,2.5-3C21.6,8.3,22.7,8,22.8,8c0.5-0.1,1.1,0.2,1.2,0.7s-0.2,1.1-0.7,1.2 | |
c-0.6,0.1-1.2,0.4-1.8,0.7C21.8,11,22,11.5,22,12c0,1.1-0.9,2-2,2s-2-0.9-2-2C18,12,18,11.9,18,11.9L18,11.9z M8,8.8 | |
C8.2,8.2,8.7,7.9,9.2,8c0,0,1.1,0.3,2.2,0.8c1.1,0.6,2.5,1.6,2.6,3c0,0,0,0.1,0,0.1c0,1.1-0.9,2-2,2s-2-0.9-2-2c0-0.5,0.2-1,0.5-1.4 | |
C10,10.4,9.3,10.1,8.8,10C8.2,9.8,7.9,9.3,8,8.8L8,8.8z M16,26c-3.6,0-6.8-1.9-8.6-4.9l2.6-1.5c1.2,2,3.5,3.4,6,3.4s4.8-1.4,6-3.4 | |
l2.6,1.5C22.8,24.1,19.6,26,16,26z"/> | |
<path id="cool" d="M16,0C7.2,0,0,7.2,0,16s7.2,16,16,16s16-7.2,16-16S24.8,0,16,0z M16,26c-1.5,0-2.9-0.3-4.2-0.9l1-1.7 | |
c1,0.4,2.1,0.7,3.2,0.7c2.9,0,5.5-1.6,6.9-3.9l1.7,1C22.8,24.1,19.6,26,16,26L16,26z M26,12c0,1.1-0.9,2-2,2h-4c-1.1,0-2-0.9-2-2h-4 | |
c0,1.1-0.9,2-2,2H8c-1.1,0-2-0.9-2-2V9c0-0.6,0.4-1,1-1h6c0.6,0,1,0.4,1,1v1h4V9c0-0.6,0.5-1,1-1h6c0.5,0,1,0.4,1,1V12z"/> | |
<path id="confused" d="M16,0C7.2,0,0,7.2,0,16s7.2,16,16,16s16-7.2,16-16S24.8,0,16,0z M22,8c1.1,0,2,0.9,2,2s-0.9,2-2,2s-2-0.9-2-2 | |
S20.9,8,22,8z M10,8c1.1,0,2,0.9,2,2s-0.9,2-2,2s-2-0.9-2-2S8.9,8,10,8z M21.5,25.3c-2.6,0.9-5.5-0.4-6.4-3 | |
c-0.6-1.6-2.3-2.4-3.8-1.8c-1.4,0.5-2.2,2-1.9,3.5h-2c-0.3-2.3,1-4.5,3.2-5.3c2.6-0.9,5.5,0.4,6.4,3c0.6,1.6,2.3,2.4,3.8,1.8 | |
c1.4-0.5,2.2-2,1.9-3.5h2C25,22.3,23.7,24.5,21.5,25.3z"/> | |
<path id="sad" d="M16,0C7.2,0,0,7.2,0,16s7.2,16,16,16s16-7.2,16-16S24.8,0,16,0z M22,8c1.1,0,2,0.9,2,2s-0.9,2-2,2s-2-0.9-2-2 | |
S20.9,8,22,8z M10,8c1.1,0,2,0.9,2,2s-0.9,2-2,2s-2-0.9-2-2S8.9,8,10,8z M22,24.4c-1.2-2-3.5-3.4-6-3.4s-4.8,1.4-6,3.4l-2.6-1.5 | |
C9.2,19.9,12.4,18,16,18s6.8,1.9,8.6,4.9L22,24.4z"/> | |
<path id="shocked" d="M16,0C7.2,0,0,7.2,0,16s7.2,16,16,16s16-7.2,16-16S24.8,0,16,0z M10,14c-1.1,0-2-1.3-2-3s0.9-3,2-3s2,1.3,2,3 | |
S11.1,14,10,14z M16,26c-2.2,0-4-1.8-4-4s1.8-4,4-4s4,1.8,4,4S18.2,26,16,26z M22,14c-1.1,0-2-1.3-2-3s0.9-3,2-3s2,1.3,2,3 | |
S23.1,14,22,14z"/> | |
<path id="wondering" d="M16,0C7.2,0,0,7.2,0,16s7.2,16,16,16s16-7.2,16-16S24.8,0,16,0z M22,8c1.1,0,2,0.9,2,2s-0.9,2-2,2s-2-0.9-2-2 | |
S20.9,8,22,8z M8,10c0-1.1,0.9-2,2-2s2,0.9,2,2s-0.9,2-2,2S8,11.1,8,10z M10.4,25.2l-0.7-2.4l13.7-4l0.7,2.4L10.4,25.2z"/> | |
<path id="angry" d="M16,0C7.2,0,0,7.2,0,16s7.2,16,16,16s16-7.2,16-16S24.8,0,16,0z M18,11.9c0.1-1.5,1.4-2.5,2.5-3 | |
C21.6,8.3,22.7,8,22.8,8c0.5-0.1,1.1,0.2,1.2,0.7s-0.2,1.1-0.7,1.2c-0.6,0.1-1.2,0.4-1.8,0.7C21.8,11,22,11.5,22,12c0,1.1-0.9,2-2,2 | |
s-2-0.9-2-2C18,12,18,11.9,18,11.9L18,11.9z M8,8.8C8.2,8.2,8.7,7.9,9.2,8c0,0,1.1,0.3,2.2,0.8c1.1,0.6,2.5,1.6,2.6,3 | |
c0,0,0,0.1,0,0.1c0,1.1-0.9,2-2,2s-2-0.9-2-2c0-0.5,0.2-1,0.5-1.4C10,10.4,9.3,10.1,8.8,10C8.2,9.8,7.9,9.3,8,8.8L8,8.8z M22,24.4 | |
c-1.2-2-3.5-3.4-6-3.4s-4.8,1.4-6,3.4l-2.6-1.5C9.2,19.9,12.4,18,16,18s6.8,1.9,8.6,4.9L22,24.4z"/> | |
<path id="baffled" d="M16,0C7.2,0,0,7.2,0,16s7.2,16,16,16s16-7.2,16-16S24.8,0,16,0z M8,13c0-1.7,1.3-3,3-3s3,1.3,3,3s-1.3,3-3,3 | |
S8,14.7,8,13z M20,24h-8v-2h8V24z M21,16c-1.7,0-3-1.3-3-3s1.3-3,3-3s3,1.3,3,3S22.7,16,21,16z M12,13c0,0.6-0.4,1-1,1s-1-0.4-1-1 | |
s0.4-1,1-1S12,12.4,12,13z M22,13c0,0.6-0.4,1-1,1s-1-0.4-1-1s0.4-1,1-1S22,12.4,22,13z"/> | |
<path id="smile" d="M16,0C7.2,0,0,7.2,0,16s7.2,16,16,16s16-7.2,16-16S24.8,0,16,0z M22,8c1.1,0,2,0.9,2,2s-0.9,2-2,2s-2-0.9-2-2 | |
S20.9,8,22,8z M10,8c1.1,0,2,0.9,2,2s-0.9,2-2,2s-2-0.9-2-2S8.9,8,10,8z M16,26c-3.6,0-6.8-1.9-8.6-4.9l2.6-1.5c1.2,2,3.5,3.4,6,3.4 | |
s4.8-1.4,6-3.4l2.6,1.5C22.8,24.1,19.6,26,16,26z"/> | |
<path id="sleepy" d="M16,0C7.2,0,0,7.2,0,16s7.2,16,16,16s16-7.2,16-16S24.8,0,16,0z M9.7,10.3c-0.4,0.4-1,0.4-1.4,0s-0.4-1,0-1.4 | |
c1.4-1.4,4-1.4,5.4,0c0.4,0.4,0.4,1,0,1.4c-0.2,0.2-0.5,0.3-0.7,0.3s-0.5-0.1-0.7-0.3C11.7,9.7,10.3,9.7,9.7,10.3z M16,26 | |
c-2.2,0-4-2.2-4-5s1.8-5,4-5s4,2.2,4,5S18.2,26,16,26z M23.7,10.3c-0.2,0.2-0.5,0.3-0.7,0.3s-0.5-0.1-0.7-0.3c-0.6-0.6-2-0.6-2.6,0 | |
c-0.4,0.4-1,0.4-1.4,0s-0.4-1,0-1.4c1.4-1.4,4-1.4,5.4,0C24.1,9.3,24.1,9.9,23.7,10.3z"/> | |
<path id="tongue" d="M16,0C7.2,0,0,7.2,0,16s7.2,16,16,16s16-7.2,16-16S24.8,0,16,0z M10,8c1.1,0,2,0.9,2,2s-0.9,2-2,2s-2-0.9-2-2 | |
S8.9,8,10,8z M24,20h-2v3c0,1.7-1.3,3-3,3s-3-1.3-3-3v-3H8v-2h16V20z M22,12c-1.1,0-2-0.9-2-2s0.9-2,2-2s2,0.9,2,2S23.1,12,22,12z"/> | |
<path id="grin" d="M16,0C7.2,0,0,7.2,0,16s7.2,16,16,16s16-7.2,16-16S24.8,0,16,0z M22,7.4c2,0,3.6,1.6,3.6,3.6 | |
c0,0.2,0,0.4-0.1,0.6c-0.1,0.3-0.3,0.5-0.6,0.5s-0.6-0.2-0.6-0.5c-0.2-1.1-1.2-1.7-2.3-1.7s-2.1,0.5-2.3,1.7c0,0.3-0.3,0.5-0.6,0.5 | |
l0,0c-0.3,0-0.6-0.2-0.6-0.5c0-0.2-0.1-0.4-0.1-0.6C18.4,9,20,7.4,22,7.4L22,7.4z M10,7.4c2,0,3.6,1.6,3.6,3.6c0,0.2,0,0.4-0.1,0.6 | |
c-0.1,0.3-0.3,0.5-0.6,0.5s-0.6-0.2-0.6-0.5c-0.2-1.1-1.2-1.7-2.3-1.7s-2.1,0.5-2.3,1.7c-0.1,0.3-0.3,0.5-0.6,0.5l0,0 | |
c-0.3,0-0.6-0.2-0.6-0.5c0-0.2-0.1-0.4-0.1-0.6C6.4,9,8,7.4,10,7.4L10,7.4z M6,18h6v7.7C8.6,24.9,6,21.7,6,18z M14,26v-8h4v8H14z | |
M20,25.7V18h6C26,21.7,23.4,24.9,20,25.7z"/> | |
<path id="neutral" d="M16,0C7.2,0,0,7.2,0,16s7.2,16,16,16s16-7.2,16-16S24.8,0,16,0z M20,24h-8v-2h8V24z M22,8c1.1,0,2,0.9,2,2 | |
s-0.9,2-2,2s-2-0.9-2-2S20.9,8,22,8z M10,8c1.1,0,2,0.9,2,2s-0.9,2-2,2s-2-0.9-2-2S8.9,8,10,8z"/> | |
</defs> | |
<g class="dotGroup"> | |
<g class="dotContainer" filter="url(#goo)" > | |
<rect class="hitArea"/> | |
</g> | |
<g class="iconContainer"/> | |
<g class="bubbleContainer"/> | |
</g> | |
<g class="shine" opacity="0"> | |
<!-- <circle fill="rgba(72, 139, 218, 0)" stroke="#C6FF69" stroke-width="0" stroke-miterlimit="10" cx="400" cy="300" r="50"/> --> | |
<ellipse id="shineM" fill="#FFF" opacity="0.12" stroke="none" stroke-width="0" stroke-miterlimit="10" cx="399" cy="277" rx="20" ry="12"/> | |
<ellipse id="shineL" fill="#FFF" opacity="0.12" stroke="none" stroke-width="0" stroke-miterlimit="10" cx="420" cy="277" rx="10" ry="5"/> | |
<ellipse id="shineR" fill="#FFF" opacity="0.12" stroke="none" stroke-width="0" stroke-miterlimit="10" cx="420" cy="277" rx="10" ry="5"/> | |
</g> | |
</svg> | |
</div> |
console.clear(); | |
var xmlns = "http://www.w3.org/2000/svg", | |
xlinkns = "http://www.w3.org/1999/xlink", | |
select = function(s) { | |
return document.querySelector(s); | |
}, | |
selectAll = function(s) { | |
return document.querySelectorAll(s); | |
}, | |
container = select('.container'), | |
dotContainer = select('.dotContainer'), | |
iconContainer = select('.iconContainer'), | |
bubbleContainer = select('.bubbleContainer'), | |
hitArea = select('.hitArea'), | |
dotGroup = select('.dotGroup'), | |
spacer = 60, | |
minDragX, | |
numItems = 20, | |
dotSize = 10, | |
//step, = spacer + (dotSize / 2), | |
snapArray = [], | |
multiplier = 4.8, | |
iconArray = [ 'evil', 'cool', 'confused', 'sad', 'shocked', 'smile', 'wondering', 'happy','angry', 'baffled', 'sleepy', 'tongue', 'grin', 'neutral'], | |
numItems = iconArray.length, | |
currentIconId, | |
oldIconId = -1, | |
currentSpeechBubble, | |
dragger, | |
uiColor = '#FF5EAE', | |
textColor = '#FF5EAE', | |
iconColor = '#FFF', | |
bubbleFillColor = '#FFF' | |
//center the container cos it's pretty an' that | |
TweenMax.set(container, { | |
position: 'absolute', | |
top: '50%', | |
left: '50%', | |
xPercent: -50, | |
yPercent: -50 | |
}) | |
TweenMax.set('svg', { | |
visibility: 'visible' | |
}) | |
//set colour | |
TweenMax.set(['line'], { | |
stroke:uiColor | |
}) | |
TweenMax.set(['.speechBubbleFill'], { | |
fill:bubbleFillColor | |
}) | |
TweenMax.set(['.speechBubbleStroke'], { | |
stroke:uiColor | |
}) | |
TweenMax.set(['.dot'], { | |
fill:uiColor | |
}) | |
TweenMax.set([ '.iconLabel'], { | |
fill:textColor | |
}) | |
var mainTl = new TimelineMax({ | |
paused: true | |
}); | |
function makeMenu() { | |
var tl; | |
for (var i = 0; i < numItems; i++) { | |
var c = select('.dot').cloneNode(true); | |
//c.data.btnId = i; | |
//var tg = select('.textGroup').cloneNode(true); | |
//var t = tg.querySelector('.label'); //.cloneNode(true); | |
var ic = select('#' +iconArray[i]).cloneNode(true); | |
ic.setAttribute('class', 'icon'); | |
dotContainer.appendChild(c); | |
iconContainer.appendChild(ic); | |
c.setAttributeNS(null, 'btnId', i); | |
TweenMax.set(c, { | |
attr: { | |
cx: (i * spacer), | |
r: dotSize | |
} | |
}) | |
TweenMax.set(ic, { | |
x: (i * spacer) - 16, | |
y:300 - 16, | |
width:0, | |
height:0, | |
transformOrigin:'50% 50%', | |
scale:0, | |
alpha:0, | |
fill:iconColor | |
}) | |
//t.textContent = (i + 1); | |
snapArray.push((-i * (spacer))); | |
tl = new TimelineMax({}); | |
tl.to(c, 1, { | |
attr: { | |
r: dotSize * multiplier | |
}, | |
ease: Linear.easeNone | |
}) | |
.to(ic, 1, { | |
alpha: 1, | |
scale: 2, | |
ease: Linear.easeNone | |
}, '-=1') | |
.to(c, 1, { | |
attr: { | |
r: dotSize | |
}, | |
ease: Linear.easeNone | |
}) | |
.to(ic, 1, { | |
alpha: 0, | |
scale: 0, | |
ease: Linear.easeNone | |
}, '-=1') | |
mainTl.add(tl, (i / 2)); | |
} | |
minDragX = (-(numItems - 1) * spacer); | |
dragger = Draggable.create(dotContainer, { | |
type: 'x', | |
bounds: { | |
minX: minDragX, | |
maxX: 0 | |
}, | |
onDrag: dragSlider, | |
onDragStart: dragStart, | |
onThrowUpdate: dragSlider, | |
throwProps: true, | |
onThrowComplete: throwComplete, | |
minDuration: 1, | |
snap: snapArray | |
}) | |
dragger[0].disable(); | |
TweenMax.set(dotGroup, { | |
x: 400 | |
}) | |
TweenMax.set(hitArea, { | |
width: dotContainer.getBBox().width, | |
height: dotSize * multiplier * 2, | |
x: dotContainer._gsTransform.x, | |
y: select('.dot').getAttribute('cy') - ((dotSize * multiplier)), | |
fill: 'transparent' | |
}) | |
TweenMax.to([dotContainer, iconContainer], 2, { | |
x: (snapArray[Math.floor(numItems / 2)]), | |
onUpdate: dragSlider, | |
onComplete: function(){ | |
throwComplete(); | |
dragger[0].enable(); | |
}, | |
ease:Elastic.easeOut.config(1, 0.85) | |
}) | |
createSpeechBubble(); | |
} //end function | |
function dragSlider() { | |
var posX = dotContainer._gsTransform.x; | |
//console.log(posX) | |
TweenMax.to(mainTl, 0.5, { | |
//time:((posX/minDragX) * (mainTl.duration()-2))+1, | |
time: ((posX / minDragX) * (mainTl.duration() - 2)) + 1, | |
ease: Elastic.easeOut.config(2, 0.75) | |
}) | |
//mainTl.time(((posX/minDragX) * (mainTl.duration()-2))+1) | |
TweenMax.set(iconContainer, { | |
x: posX | |
}) | |
TweenMax.to( bubbleContainer,1, { | |
x: posX, | |
ease:Elastic.easeOut.config(1, 0.5) | |
}) | |
} | |
function throwComplete() { | |
//var segId = Math.round(normalizedRotation / rotationStep) | |
var landed = Math.ceil(dotContainer._gsTransform.x / spacer); | |
currentIconId = Math.abs(landed); | |
//currentIconId = bubbleId; | |
//console.log(iconArray[currentIconId]) | |
showSpeechBubble(); | |
/*console.log(bubbleId) | |
TweenMax.to('.shine', 0.2, { | |
alpha: 0.8 | |
}) | |
TweenMax.set('#shineL', { | |
alpha: (bubbleId == 0) ? 0 : 0.12 | |
}) | |
TweenMax.set('#shineR', { | |
alpha: (bubbleId == (numItems - 1)) ? 0 : 0.12 | |
}) | |
*/ | |
} | |
function createSpeechBubble(){ | |
currentSpeechBubble = select('.speechBubbleGroup').cloneNode(true); | |
bubbleContainer.appendChild(currentSpeechBubble); | |
TweenMax.set(currentSpeechBubble, { | |
y:80, | |
scale:0, | |
transformOrigin:'50% 100%' | |
}) | |
} | |
function showSpeechBubble(){ | |
currentSpeechBubble.querySelector('text').textContent = iconArray[currentIconId].toUpperCase(); | |
var tl = new TimelineMax(); | |
tl.set(currentSpeechBubble, { | |
x:currentIconId * spacer - (currentSpeechBubble.getBBox().width/2) - 5, | |
rotation:(oldIconId < currentIconId) ? 45 : -45 | |
}) | |
.to(currentSpeechBubble, 1, { | |
rotation:0, | |
ease:Elastic.easeOut.config(1, 0.6), | |
scaleX:1 | |
}) | |
.to(currentSpeechBubble, 0.6, { | |
ease:Elastic.easeOut.config(1, 0.6), | |
//alpha:1, | |
scaleY:1 | |
},'-=1') | |
} | |
function clearSpeechBubble(){ | |
var pl = select('.popLines').cloneNode(true); | |
bubbleContainer.appendChild(pl); | |
var tl = new TimelineMax({onComplete:function(){ | |
if(this.data.lines){ | |
bubbleContainer.removeChild(this.data.lines); | |
} | |
}}); | |
tl.data = {lines:pl}; | |
tl.set(pl, { | |
x:currentSpeechBubble._gsTransform.x, | |
y:currentSpeechBubble._gsTransform.y, | |
transformOrigin:'50% 50%', | |
scale:0.8 | |
}) | |
.to(pl.querySelectorAll('line'), 0.3, { | |
drawSVG:'100% 100%', | |
ease:Linear.easeNone | |
}) | |
.to(pl, 0.3, { | |
scale:1.4, | |
ease:Expo.easeOut | |
},'-=0.3') | |
TweenMax.set(currentSpeechBubble, { | |
scale:0 | |
}) | |
} | |
function dragStart(){ | |
clearSpeechBubble() | |
} | |
document.body.onclick = function(e){ | |
//console.log(e.target.className.baseVal) | |
if(e.target.className.baseVal !== 'dot'){ | |
return; | |
} | |
//console.log(e.target.getAttribute('btnId')); | |
oldIconId = currentIconId; | |
currentIconId = parseInt(e.target.getAttribute('btnId')); | |
if(oldIconId == currentIconId){ | |
return | |
} | |
clearSpeechBubble(); | |
TweenMax.to([dotContainer, iconContainer], 0.8, { | |
x: (snapArray[currentIconId]), | |
onUpdate: dragSlider, | |
onComplete: throwComplete, | |
ease:Power1.easeOut | |
//ease:Back.easeOut | |
}) | |
} | |
makeMenu(); |
<script src="//cdnjs.cloudflare.com/ajax/libs/gsap/1.18.2/TweenMax.min.js"></script> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/1.18.2/utils/Draggable.min.js"></script> | |
<script src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/16327/ThrowPropsPlugin.min.js"></script> | |
<script src="//s3-us-west-2.amazonaws.com/s.cdpn.io/16327/DrawSVGPlugin.js?r=12"></script> |
body { | |
background-color:#2d2d2d; | |
overflow: hidden; | |
/* font-family: 'Fjalla One', sans-serif; */ | |
font-family: 'Passion One', sans-serif; | |
} | |
body, | |
html { | |
height: 100%; | |
width: 100%; | |
margin: 0; | |
padding: 0; | |
} | |
.container{ | |
position:absolute; | |
max-width:100%; | |
} | |
svg{ | |
max-width:100%; | |
visibility:hidden; | |
/* overflow:visible; */ | |
} | |
.shine, .iconContainer{ | |
pointer-events:none; | |
} | |
.dot{ | |
cursor:pointer; | |
} | |
.shine circle{ | |
stroke:#FFF; | |
} | |
.speechBubbleGroup text{ | |
text-anchor:middle; | |
font-size:29px; | |
} | |
line{ | |
vector-effect:"non-scaling-stroke"; | |
} |
A dynamic menu I've built that can be used with either icons or text for the slider bubbles.
This one is a fun emoticon rating slider - you can drag and throw or just click to show how you feel.
A Pen by Chris Gannon on CodePen.