170 lines
6.3 KiB

define(function(require, exports, module) {
var Group = require('graphic/group');
var Circle = require('graphic/circle');
var Color = require('graphic/color');
var Text = require('graphic/text');
var Pen = require('graphic/pen');
var Matrix = require('graphic/matrix');
var Pie = require('../ringpalette/pie');
var Draggable = require('../public/draggable');
return require('core/class').createClass({
base: Group,
mixins: [Draggable],
constructor: function(innerRadius, outerRadius, trackCount, trackPieCount, initSaturation) {
this.callBase();
this.innerRadius = innerRadius || 200;
this.outerRadius = outerRadius || 400;
this.trackCount = trackCount || 12;
this.trackHeight = (this.outerRadius - this.innerRadius) / this.trackCount;
this.trackPieCount = trackPieCount || 60;
this.saturation = initSaturation || 50;
this.generate();
this.control();
this.callMixin();
this.drag();
},
generate: function() {
this.generateCircle();
this.generateTracks();
this.generateLabels();
},
generateCircle: function() {
this.circle = new Circle(this.innerRadius);
this.circle.stroke(new Pen('white', 5));
this.circle.setStyle('cursor', 'move');
this.addShape(this.circle);
},
generateTracks: function() {
this.pies = new Group();
for (var trackNumber = 0; trackNumber < this.trackCount; trackNumber++) {
this.pies.addShapes(this.generateTrackPies(trackNumber));
}
this.addShape(this.pies.rotate(0));
},
generateTrackPies: function(trackNumber) {
var trackInnerRadius = this.innerRadius + this.trackHeight * trackNumber,
trackOuterRadius = trackInnerRadius + this.trackHeight;
var h,
s = this.saturation,
l = this.getTrackLightness(trackNumber);
var color, pie;
var hStep = 360 / this.trackPieCount;
var trackPies = [];
for (h = 0; h < 360; h += hStep) {
color = Color.createHSL(h, s, l);
pie = new Pie(trackInnerRadius + 1, trackOuterRadius, h + 0.2, h + hStep - 0.2);
pie.fill(pie.color = color);
trackPies.push(pie);
}
return trackPies;
},
getTrackLightness: function(trackNumber) {
var lMin = 20,
lMax = 95;
return lMin + trackNumber / this.trackCount * (lMax - lMin);
},
generateLabels: function() {
var fontSize = this.innerRadius / 6;
this.rgbLabel = new Text().setTextAnchor('middle').setSize(fontSize).setY(-this.innerRadius / 8);
this.hslLabel = new Text().setTextAnchor('middle').setSize(fontSize).setY(this.innerRadius / 4);
this.addShape(this.rgbLabel);
this.addShape(this.hslLabel);
},
control: function() {
var ring = this;
this.on('mouseover', function(e) {
var pie = e.targetShape;
if (pie.getClass() == Pie) {
var color = pie.color;
pie.setScale(2).setTranslate(-pie.center.x, -pie.center.y);
pie.stroke('white');
ring.setCircleColor(color);
ring.bringFront(pie);
}
e.stopPropagation();
e.preventDefault();
});
this.on('mouseout', function(e) {
var pie = e.targetShape;
if (pie.getClass() == Pie) {
pie.setScale(1).setTranslate(0, 0);
pie.stroke('none');
ring.showSelected();
}
});
this.on('click', function(e) {
var pie = e.targetShape;
if (pie.getClass() == Pie) {
ring.selectedPie(pie);
}
});
},
selectedPie: function(pie) {
if (this.selected) {
this.selected.stroke('none');
}
this.selected = pie;
},
showSelected: function() {
var pie = this.selected,
pen;
if (pie) {
pen = new Pen().setWidth(5).setColor('white');
pie.stroke(pen);
this.bringFront(pie);
this.setCircleColor(pie.color);
}
},
setCircleColor: function(color) {
this.circle.color = color;
this.circle.fill(color);
var labelColor = color.get('l') >= 50 ?
color.dec('l', 50).set('s', 10) :
color.inc('l', 50).set('s', 10);
this.rgbLabel.setContent(color.toRGB()).fill(labelColor);
this.hslLabel.setContent(color.toHSL()).fill(labelColor);
},
bringFront: function(obj) {
obj.container.removeShape(obj).addShape(obj);
},
updateSaturation: function(s) {
this.s = s;
this.pies.eachItem(function(index, pie) {
pie.fill(pie.color.set('s', s));
});
if (this.circle.color) {
this.setCircleColor(this.circle.color.set('s', s));
}
},
getPan: function() {
this.pan = this.pan || {
min: -this.outerRadius * 0.8,
max: this.outerRadius * 0.8,
length: this.outerRadius * 1.6,
value: 0
};
return this.pan;
},
drag: function() {
return this.callMixin({
target: this.circle,
move: function(e) {
var pan = this.getPan();
pan.value += e.delta.x;
pan.value = Math.min(pan.value, pan.max);
pan.value = Math.max(pan.value, pan.min);
this.updateSaturation(100 * (pan.value - pan.min) / pan.length);
this.updatePosition(pan.value);
}
});
},
updatePosition: function(x) {
this.setTranslate(x, 0);
}
});
});