JavaScript
语言:
JaveScriptBabelCoffeeScript
确定
const opts = {
width: 720,
height: 600,
};
const COLORS = ["f1c40f", "2ecc71", "3498db", "9b59b6", "34495e", "c0392b", "7f8c8d", "1abc9c"];
const App = (() => {
const model = {
inputs: {
name: m.stream(""),
value: m.stream("")
},
valueList: [{
name: "Isn't this cool",
value: 10,
id: 0
}, {
name: "Now there's titles",
value: 3,
id: 1
}, {
name: "I know right?",
value: 6.7,
id: 2
}],
controls: {
radius: m.stream(100),
thickness: m.stream(10),
gap: m.stream(1),
listOffset: m.stream(10),
}
}
const ctrl = {
handle: {
input: {
name: (e) => {
e.preventDefault();
model.inputs.name(e.target.value);
},
value: (e) => {
e.preventDefault();
let val = e.target.value.replace(/[^0-9.]/g, "").replace(/(\.)\1/g, ".");
model.inputs.value(val);
},
submit: (e) => {
e.preventDefault();
let id = model.valueList.length,
name = model.inputs.name(),
value = model.inputs.value();
name != "" && value != "" ? model.valueList.push({
name: name,
value: value,
id: id
}) : void 0;
model.inputs.name("");
model.inputs.value("");
}
},
control: {
thickness: (e) => {
model.controls.thickness(e.target.value);
},
radius: (e) => {
console.log(e.target.value)
model.controls.radius(e.target.value);
}
}
},
removeValue: (val) => {
model.valueList = model.valueList.filter((el) => {
return el.id !== val.id;
})
}
}
function view(vnode) {
let list = model.valueList.map((el, ind) => {
el.remove = () => {
ctrl.removeValue({
id: el.id
});
}
el.view = (vnode) => {
return m("div.values--value-item", [
m("p.values--value-item-value", vnode.attrs.value),
m("p.values--value-item-name", vnode.attrs.name),
m("button", {
onclick: el.remove
}, String.fromCharCode(215))
])
}
return m(el, {
name: el.name,
value: el.value,
});
});
return m("div.app--container", {
style: "width: " + opts.width + "px; height: " + opts.height + "px"
}, [
m("div.app--values--wrapper", [
m("p.app--title", "Values"),
m("div.app--values--input-wrapper", [
m("div.values--description", [
m("div.values--description-name", "Name"),
m("div.values--description-value", "Value"),
]),
m("div.values--list", list),
m("form.values--input", {
onsubmit: ctrl.handle.input.submit
}, [
m("input.values--input-submit", {
type: "submit",
value: String.fromCharCode(215),
}),
m("input.values--input-name", {
oninput: ctrl.handle.input.name,
value: model.inputs.name(),
placeholder: "Name..."
}),
m("input.values--input-value", {
oninput: ctrl.handle.input.value,
value: model.inputs.value(),
placeholder: "Value.."
})
])
])
]),
m("div.app--canvas--wrapper", [
m("p.app--title", "Result"),
m(Canvas, {
width: 432,
height: 320,
list: model.valueList,
controls: model.controls
}),
]),
m("div.app--controls--wrapper", [
m("p.app--title", "Controls"),
m("div.app--controls--holder", [
m("div.app--controls--input", [
m("label.app--controls--label", {
for: "thickness-control"
}, "Thickness"),
m("input.app--controls--thickness", {
id: "thickness-control",
className: "app--controls--thickness slider",
type: "range",
min: "1",
max: "30",
oninput: ctrl.handle.control.thickness,
value: model.controls.thickness()
}),
]),
m("div.app--controls--input", [
m("label.app--controls--label", {
for: "radius-control"
}, "Radius"),
m("input.app--controls--radius", {
id: "radius-control",
className: "slider",
type: "range",
min: "10",
max: "100",
oninput: ctrl.handle.control.radius,
value: model.controls.radius()
})
])
]),
]),
]);
}
return {
view: view
}
});
const Canvas = (() => {
const model = {
dom: null
}
const ctrl = {
render: (vnode) => {
let $ = model.dom.getContext("2d"),
w = model.dom.width,
h = model.dom.height,
list = vnode.attrs.list,
pi = Math.PI,
pi2 = pi * 2,
piDeg = Math.PI / 180,
ctrls = vnode.attrs.controls;
let total = list.reduce((s, val) => {
val.value = +val.value;
return s + val.value;
}, 0),
totalListHeight = list.length * 3 * 10,
middleTopOffset = h / 2 - totalListHeight / 2;
$.fillStyle = "white";
$.fillRect(0, 0, w, h);
for (let i = 0, val = 0; i < list.length; i++) {
$.beginPath();
$.arc(+ctrls.radius() + ctrls.thickness() * 2, h / 2, +ctrls.radius(), (val / total) * pi2 + piDeg * ctrls.gap(), (val += list[i].value) / total * pi2 - piDeg * ctrls.gap());
$.strokeStyle = "#" + COLORS[i];
$.lineWidth = ctrls.thickness();
$.stroke();
$.fillStyle = "#" + COLORS[i];
$.save();
$.translate(ctrls.radius() * 2 + ctrls.thickness() * 3 + ctrls.listOffset(), middleTopOffset + 10 * i * 3);
$.fillRect(0, 0, 10, 10);
$.font = 15 + "px Open Sans";
$.fillStyle = "black";
$.fillText(list[i].name, 2 * 10, 10)
$.restore();
};
}
}
function oncreatedom(vnode) {
model.dom = vnode.dom;
ctrl.render(vnode)
}
function view(vnode) {
model.dom ? ctrl.render(vnode) : void 0;
return m("canvas", {
width: vnode.attrs.width,
height: vnode.attrs.height
})
}
return {
view: view,
oncreate: oncreatedom
};
})
m.route(document.body, "/app", {
"/app": App
});