dat.gui/number.html

270 lines
5.5 KiB
HTML
Raw Normal View History

2014-08-14 21:50:51 +00:00
<link rel="import" href="components/polymer/polymer.html">
<polymer-element name="gui-number" attributes="min max value step" constructor="NumberController">
<template>
<style>
:host {
display: block;
-webkit-text-select: none;
font-size: 0;
margin-bottom: 2px;
height: 20px;
}
:host * {
margin: 0;
}
#track-container {
height: 20px;
width: 100%;
}
#track {
width: 100%;
margin-top: 5px;
height: 10px;
margin-right: 2px;
display: inline-block;
vertical-align: top;
position: relative;
border-radius: 20px;
background: rgba( 0, 0, 0, 0.1 );
opacity: 0.9;
-webkit-transition: opacity 0.2s ease-out;
}
#fill {
height: 8px;
margin-top: 1px;
margin-left: 1px;
border-radius: 10px;
position: absolute;
background: #fff;
pointer-events: none;
opacity: 0.9;
-webkit-transition: opacity 0.2s ease-out;
}
#container:hover #fill,
#container:hover #track {
opacity: 1;
}
#container.transition #knob {
-webkit-transition: left 0.1s ease-out;
}
#container.transition #fill {
-webkit-transition: width 0.1s ease-out;
}
#knob {
position: absolute;
pointer-events: none;
width: 12px;
height: 12px;
background-color: #fff;
border-radius: 100%;
margin-left: -6px;
margin-top: -1px;
box-shadow: 0 1px 0 rgba( 0, 0, 0, 0.2 );
}
.straddle-zero #knob {
}
.negative #knob,
.negative #fill {
background: #333;
}
input {
display: inline-block;
vertical-align: top;
background: transparent;
border: 0;
text-align: center;
outline: none;
font: bold 10px sans-serif;
color: #fff;
-webkit-font-smoothing: antialiased;
}
</style>
<div id="container" horizontal layout>
<div id="track-container"
on-down="{{ down }}"
on-trackx="{{ trackx }}"
on-trackstart="{{ trackstart }}"
flex>
<div id="track">
<div id="fill">
</div>
<div id="knob">
</div>
</div>
</div>
<input type="text" value="{{ value }}">
</template>
</div>
<script>
Polymer('gui-number', {
min: 0,
max: 100,
step: 1,
value: 50,
object: null,
property: null,
ready: function() {
var _this = this;
window.addEventListener( 'keydown', function( e ) {
if ( e.keyCode == 18 ) _this._alt = true;
}, false );
window.addEventListener( 'keyup', function( e ) {
if ( e.keyCode == 18 ) _this._alt = false;
}, false );
this.update();
},
objectChanged: function() {
if ( this.property ) {
this._boundToObject = true;
this.value = this.object[ this.property ];
}
},
propertyChanged: function() {
if ( this.object ) {
this._boundToObject = true;
this.value = this.object[ this.property ];
}
},
valueChanged: function() {
this.value = Math.max( this.value, this.min );
this.value = Math.min( this.value, this.max );
if ( this._boundToObject ) this.object[ this.property ] = this.value;
this.update();
},
minChanged: function() {
this.value = Math.max( this.value, this.min );
this.update();
},
maxChanged: function() {
this.value = Math.min( this.value, this.max );
this.update();
},
update: function() {
var ratio = this.map( this.value, this.min, this.max, 0, 1 );
if ( this.min < 0 && this.max > 0 ) {
this.$.container.classList.add( 'straddle-zero' );
var zero = this.map( 0, this.min, this.max, 0, 1 );
if ( this.value >= 0 ) {
this.$.fill.style.left = zero * 100 + '%';
this.$.fill.style.width = (ratio - zero) * 100 + '%';
this.$.fill.style.right = '';
} else {
this.$.fill.style.left = '';
this.$.fill.style.width = (zero - ratio) * 100 + '%';
this.$.fill.style.right = ( 1 - zero ) * 100 + '%';
}
} else {
this.$.container.classList.remove( 'straddle-zero' );
this.$.fill.style.left = 0;
this.$.fill.style.width = ratio * 100 + '%';
this.$.fill.style.right = '';
}
this.$.knob.style.left = ratio * 100 + '%';
this.$.container.classList.toggle( 'positive', this.value >= 0 );
this.$.container.classList.toggle( 'negative', this.value < 0 );
},
// Events
// -------------------------------
down: function( e ) {
e.preventDefault();
this.$.container.classList.add( 'transition' );
this._rect = this.$.track.getBoundingClientRect();
if ( !this._alt ) this.setValueFromX( e.x );
},
trackstart: function( e ) {
this.$.container.classList.remove( 'transition' );
},
trackx: function( e ) {
var dv = this.setValueFromDX( e.ddx );
if ( this._alt ) dv /= 10;
this.value += dv;
},
// Helpers
// -------------------------------
setValueFromX: function( x ) {
this.value = this.map( x, this._rect.left, this._rect.right, this.min, this.max );
},
setValueFromDX: function( dx ) {
return this.map( dx, 0, this._rect.width, 0, this.max - this.min );
},
map: function( x, a, b, c, d ) {
return ( x - a ) / ( b - a ) * ( d - c ) + c;
}
});
</script>
</polymer-element>