SVG Component
<div id="app"></div>
<div class="template">
<div class="app">
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="300" height="200">
<rect transform?="translate(150, 100) rotate(@{ $.slider1.value }) scale(@{ $.slider2.value }, @{ $.slider3.value })"
width="20" height="20" x-style="fill: rgb(0,255,0);"></rect>
<circle cx="150" cy="100" r="2" x-style="fill: rgb(255,0,0)"></circle>
<g x-type="TextSlider" transform="translate(10, 10)" name="rotate" max="360" x-ref="slider1"></g>
<g x-type="TextSlider" transform="translate(10, 30)" name="scaleX" min="1.0" max="5.0" x-ref="slider2"></g>
<g x-type="TextSlider" transform="translate(10, 50)" name="scaleY" min="1.0" max="5.0" x-ref="slider3"></g>
</svg>
</div>
</div>
<div class="template">
<g class="text-slider" xmlns="http://www.w3.org/2000/svg">
<text transform="translate(0, 10)">&{ $.name }</text>
<text transform="translate(50, 10)">: @{ $.value }</text>
<g x-type="Slider" x-ref="slider" transform="translate(120, 0)" max&="$.max" min&="$.min" value#="$.value"></g>
</g>
</div>
<div class="template">
<g class="slider" xmlns="http://www.w3.org/2000/svg">
<rect width="100" height="2" y="5" class="track"></rect>
<circle cx@="$.normalize($.value)" cy="6" r="6" class="button" x-ref="btn" mousedown+="$.onMouseChange"></circle>
</g>
</div>
* {
font-family: "Helvetica Neue", Helvetica, Arial, "Microsoft Yahei", sans-serif;
}
.template {
display: none;
}
svg {
background-color: #eee;
user-select: none;
user-select: none;
user-select: none;
user-select:none
}
.slider .track {
fill: rgb(200,200,200);
}
.slider .button {
cursor: pointer;
fill: rgb(240,240,240);
stroke-width: 1px;
stroke: rgb(160,160,160);
}
var Component = Exact.Component;
var Skin = Exact.Skin;
function Slider() {
Component.apply(this, arguments);
}
Exact.defineClass({
constructor: Slider, extend: Component,
statics: {
defaults: function() {
return {
min: 0,
max: 10,
value: 0
};
},
template: Skin.query('.template .slider')
},
onMouseChange: function(event) {
switch (event.type) {
case 'mousemove':
if (this.pressed) {
var max = Number(this.max);
var min = Number(this.min);
//var cx = event.clientX - this.$skin.getBoundingClientRect().left;
var cx = event.clientX - Skin.call(this.$skin, 'getBoundingClientRect').left;
cx = cx < 0 ? 0 : cx;
cx = cx > 100 ? 100 : cx;
this.set('value', (cx * 0.01 * (max - min) + min).toFixed(1));
}
break;
case 'mousedown':
this.pressed = true;
break;
case 'mouseup':
this.pressed = false;
break;
}
},
register: function() {
Exact.help(this).bind('onMouseChange');
},
ready: function() {
var body = document.body;
body.addEventListener('mousemove', this.onMouseChange);
body.addEventListener('mouseup', this.onMouseChange);
var self = this;
this.on('changed', function(event) {
if (event.keyName !== 'value') {
var value = self.value;
value = value < self.min ? self.min : value;
value = value > self.max ? self.max : value;
self.set('value', value);
}
});
},
normalize: function(value) {
return (value - this.min) / (this.max - this.min) * 100;
}
});
function TextSlider() {
Component.apply(this, arguments);
}
Exact.defineClass({
constructor: TextSlider, extend: Component,
statics: {
template: Skin.query('.template .text-slider'),
resources: {
Slider: Slider
},
defaults: function() {
return {
min: 0,
max: 10,
value: 0,
label: ''
};
}
}
});
function App() {
Component.apply(this, arguments);
}
Exact.defineClass({
constructor: App, extend: Component,
statics: {
template: Skin.query('.template .app'),
resources: {
TextSlider: TextSlider
}
}
});
Component.create(App).attach(Skin.query('#app'));