1
0
forked from x/ContextOS
ContextOS/usr/wiki/html5.js
2018-09-02 21:07:20 +08:00

661 lines
17 KiB
JavaScript

var canvas = document.getElementById("heart");//{{{
var ctx = canvas.getContext('2d');
var main_angle = 30;
function refreshHeart() {
ctx.clearRect(0,0,400,400)
drawHeart(ctx,200,200,60,main_angle);
main_angle += 10;
for (var i = 0; i < 10; i++) {
var x = Math.random() * 400;
var y = Math.random() * 400;
var scale = Math.random() * 20+10;
var angle = Math.random() * 360;
drawHeart(ctx,x,y,scale,angle);
}
setTimeout(refreshHeart, 200);
}
setTimeout(refreshHeart, 200);
function drawHeart(ctx,x,y,scale,angle, style, stroke) {//{{{
ctx.save();
ctx.translate(x,y);
ctx.rotate(angle/180*Math.PI);
ctx.scale(scale, scale);
heartPath(ctx);
ctx.shadowColor = "gray";
ctx.shadowOffsetX = 5;
ctx.shadowOffsetY = 5;
ctx.shadowBlur = 5;
if (stroke == "stroke") {
ctx.strokeStyle = style||"red";
ctx.stroke();
} else {
ctx.fillStyle = style||"red";
ctx.fill();
}
ctx.restore();
}
//}}}
function heartPath(ctx) {//{{{
ctx.beginPath();
ctx.arc(-1,0,1,Math.PI,0,false);
ctx.arc(1,0,1,Math.PI,0,false);
ctx.bezierCurveTo(1.9, 1.2, 0.6, 1.6, 0, 3.0);
ctx.bezierCurveTo( -0.6, 1.6,-1.9, 1.2,-2,0);
ctx.closePath();
}
//}}}
var ctx0 = document.getElementById("demo0").getContext("2d");
ctx0.fillStyle = "green";
ctx0.fillRect(10,10,100,100);
var ctx2 = document.getElementById("demo2").getContext("2d");
ctx2.beginPath();
ctx2.moveTo(60,10);
ctx2.lineTo(10,110);
ctx2.lineTo(110,110);
ctx2.fill();
function draw3() {
for (var i = 0; i < 120; i+=20) {
for (var j = 0; j < 120; j+=20) {
r = Math.random()*255;
g = Math.random()*255;
b = Math.random()*255;
ctx3.fillStyle = "rgb("+r+","+g+","+b+")";
ctx3.fillRect(i, j, 20, 20);
}
}
}
var demo3 = document.getElementById("demo3");
var ctx3 = demo3.getContext("2d");
demo3.onclick = draw3;
draw3()
//}}}
var draw_history = [{shape:"hide"}];
var his = document.getElementById("draw_history");
var draw = document.getElementById("draw").getContext("2d");
var current_ctx = {//{{{
agent: {},
big_scale: 1.25,
small_scale: 0.8,
font: '32px sans-serif',
index_point: false,
begin_point: null,
end_point: null,
last_point: null,
last_move: 0,
config: {
shape: {value: "rect", list: [
{text: "移动", value: "move"},
{text: "隐藏", value: "hide"},
{text: "心形", value: "heart"},
{text: "圆形", value: "cycle"},
{text: "矩形", value: "rect"},
{text: "直线", value: "line"},
{text: "文字", value: "text"},
]},
stroke: {value: "stroke", list: [
{text: "画笔", value: "stroke"},
{text: "画刷", value: "fill"},
]},
color: {value: "green", list: [
{text: "黑色", value: "black"},
{text: "红色", value: "red"},
{text: "黄色", value: "yellow"},
{text: "绿色", value: "green"},
{text: "蓝色", value: "blue"},
{text: "紫色", value: "purple"},
{text: "白色", value: "white"},
]},
scale: {text: "比例", value: 1},
offsetX: {text: "X偏移", value: 0},
offsetY: {text: "Y偏移", value: 0},
point: {text: "坐标", value: "0,0"},
interval: {text: "间隔", value: 100},
json: {text: "数据", value: ""},
},
command: {
cmd_shape: {
move: {text: "移动", key: "m", conf:{"shape": "move"}},
hide: {text: "隐藏", key: "h"},
heart: {text: "心形", key: "e",
conf:{"shape": "heart", "stroke": "fill"},
cmd:{"fill": "cmd_stroke"},
},
cycle: {text: "圆形", key: "c", conf:{"shape": "cycle"}},
rect: {text: "矩形", key: "r", conf:{"shape": "rect"}},
line: {text: "直线", key: "v",
conf:{"shape": "line", "stroke": "stroke"},
cmd:{"stroke": "cmd_stroke"},
},
text: {text: "文字", key: "t",
conf:{"shape": "text", "stroke": "fill"},
cmd:{"fill": "cmd_stroke"},
},
},
cmd_stroke: {
stroke: {text: "画笔", key: "s", conf:{"stroke": "stroke"}},
fill: {text: "画刷", key: "f", conf:{"stroke": "fill"}},
},
cmd_color: {
black: {text: "黑色", key: "", conf:{"color": "black"}},
red: {text: "红色", key: "", conf:{"color": "red"}},
yellow: {text: "黄色", key: "", conf:{"color": "yellow"}},
green: {text: "绿色", key: "", conf:{"color": "green"}},
purple: {text: "紫色", key: "", conf:{"color": "purple"}},
blue: {text: "蓝色", key: "", conf:{"color": "blue"}},
white: {text: "白色", key: "", conf:{"color": "white"}},
},
ctrl_status: {
shape: {type: "config"},
stroke: {type: "config"},
color: {type: "config"},
scale: {type: "cache"},
point: {type: "cache"},
},
ctrl_show: {
big: {text: "放大", key: "+"},
small: {text: "缩小", key: "-"},
play: {text: "播放", key: "a"},
interval: {type: "config", width: 30},
},
ctrl_data: {
delete: {text: "删除", key: "d"},
clear: {text: "清空", key: "q"},
export: {text: "导出"},
import: {text: "导入"},
json: {type: "config", width: 80},
},
"": {},
},
}
//}}}
function init(configs, commands) {//{{{
current_ctx.agent.isChrome = window.navigator.userAgent.indexOf("Chrome")>-1;
current_ctx.agent.isMobile = window.navigator.userAgent.indexOf("Mobile")>-1;
for (var group in commands) {
var cs = document.getElementsByClassName(group+" bar");
for (var i = 0; i < cs.length; i++) {
for (var which in commands[group]) {
var command = commands[group][which];
var config = configs[which];
if (command.type == "cache") {
var label = cs[i].appendChild(document.createElement("label"));
label.innerText = config.text+": ";
var label = cs[i].appendChild(document.createElement("label"));
label.innerText = config.value;
label.className = "config "+which;
} else if (command.type == "config") {
if (config.list) {
var select = cs[i].appendChild(document.createElement("select"));
select.className = "config "+which;
for (var j in config.list) {
var item = config.list[j];
var option = select.appendChild(document.createElement("option"));
option.value = item.value;
option.text = item.text;
if (config.value == item.value) {
select.selectedIndex = j
}
}
(function() {
var bar = group;
var key = which;
select.onchange = function(event) {
current_ctx.config[key].value = event.target[event.target.selectedIndex].value;
}
})();
} else {
var label = cs[i].appendChild(document.createElement("label"));
label.innerText = config.text+": ";
var input = cs[i].appendChild(document.createElement("input"));
input.style.width = command.width+"px";
input.value = config.value;
input.className = "config "+which;
(function() {
var key = which;
input.onblur = function(event) {
current_ctx.config[key].value = event.target.value;
}
input.onkeyup = function(event) {
switch (event.key) {
case "Enter":
current_ctx.config[key].value = event.target.value;
break
case "Escape":
event.target.value = current_ctx.config[key].value;
break
}
}
})();
}
} else {
var cmd = cs[i].appendChild(document.createElement("button"));
cmd.className = group+" "+which;
if (command.key) {
control_map[command.key] = [group, which];
cmd.innerText = command.text+"("+command.key+")";
} else {
cmd.innerText = command.text
}
(function() {
var key = which;
var bar = group;
cmd.onclick = function(event) {
action(event, key, bar);
}
})();
}
}
}
}
}//}}}
function conf(group, which, value) {//{{{
var config = current_ctx[group][which];
if (value != undefined) {
config.value = value;
var cs = document.getElementsByClassName(group+" "+which);
for (var i = 0; i < cs.length; i++) {
if (cs[i].nodeName == "LABEL") {
cs[i].innerText = value;
} else {
cs[i].value = value;
}
}
}
return config.value
}//}}}
function info() {//{{{
var list = []
for (var i = 0; i < arguments.length; i++) {
if (typeof arguments[i] == "object") {
list.push("{")
for (var k in arguments[i]) {
list.push(k+": "+arguments[i][k]+",")
}
list.push("}")
} else {
list.push(arguments[i])
}
}
var debug_info = document.getElementsByClassName("debug_info");
for (var i = 0; i < debug_info.length; i++) {
var p = debug_info[i].appendChild(document.createElement("p"));
p.appendChild(document.createTextNode(list.join(" ")));
debug_info[i].scrollTop+=100;
}
}
//}}}
var control_map = {//{{{
Escape: ["", "escape"],
action: {
"escape": [function() {
current_ctx.begin_point = null;
current_ctx.end_point = null;
}],
"hide": [function() {
var s = {shape: "hide", time:1}
add_history(his, s);
draws(draw, s);
}],
"big": [function(){
draw.scale(current_ctx.big_scale, current_ctx.big_scale);
var m = draw.getTransform();
conf("config", "scale", m.a);
}],
"small": [function(){
draw.scale(current_ctx.small_scale, current_ctx.small_scale);
var m = draw.getTransform();
conf("config", "scale", m.a);
}],
"play": [function() {
draw.resetTransform();
conf("config", "scale", 1)
conf("config", "offsetX", 0)
conf("config", "offsetY", 0)
refresh(conf("config", "interval"), 0, "", function() {
var m = draw.getTransform();
conf("config", "scale", m.a);
conf("config", "offsetX", m.e)
conf("config", "offsetY", m.f)
});
return false
}],
"delete": [function() {
if (draw_history.length > 1) {
var tr = his.rows[his.rows.length-1];
tr.parentElement.removeChild(tr)
draw_history.pop();
}
}],
"clear": [function() {
if (confirm("clear all?")) {
draw_history.length = 1;
var th = his.rows[0];
his.innerHTML = "";
his.appendChild(th);
}
}],
"export": [function() {
conf("config", "json", JSON.stringify(draw_history));
return false
}],
"import": [function() {
var im = JSON.parse(conf("config", "json"));
for (var i in im) {
add_history(his, im[i]);
draws(draw, im[i]);
}
}],
"default": [function(event, which, group) {
var cs = document.getElementsByClassName(group);
for (var i = 0; i < cs.length; i++) {
cs[i].style.backgroundColor = "white";
}
var cs = document.getElementsByClassName(group+" "+which);
for (var i = 0; i < cs.length; i++) {
cs[i].style.backgroundColor = "lightblue";
}
}],
}
}
//}}}
function control(event) {//{{{
if (event.type == "keyup" && control_map[event.key]) {
action(event, control_map[event.key][1], control_map[event.key][0]);
}
}
//}}}
function action(event, which, group) {//{{{
var w = control_map.action[which]? which: "default";
while (control_map.action[w]) {
var command = current_ctx.command[group][which] || {};
for (var k in command.conf) {
conf("config", k, command.conf[k]);
}
for (var i in control_map.action[w]) {
var next = control_map.action[w][i](event, which, group);
w = next || w;
}
for (var k in command.cmd) {
action(event, k, command.cmd[k])
}
next == undefined && refresh()
w = next;
}
}
//}}}
function trans(point) {//{{{
return {
x: point.x/conf("config", "scale")-conf("config","offsetX"),
y: point.y/conf("config", "scale")-conf("config","offsetY"),
}
}
//}}}
function draw_point(event) {//{{{
var point = trans({
x: event.type == "touchstart"? event.touches[0].clientX: event.offsetX,
y: event.type == "touchstart"? event.touches[0].clientY: event.offsetY,
});
conf("config", "point", parseInt(point.x)+","+parseInt(point.y));
if (!current_ctx.begin_point) {
current_ctx.begin_point = point;
info(event.type, "begin_point: ", current_ctx.begin_point)
return
}
current_ctx.end_point = point;
info(event.type, "end_point: ", current_ctx.end_point)
var s = {
shape: conf("config", "shape"),
stroke: conf("config", "stroke"),
color: conf("config", "color"),
begin_point: current_ctx.begin_point,
end_point: current_ctx.end_point,
text: conf("config", "shape") == "text"? prompt("请入文字", ""): "",
};
add_history(his, s);
draws(draw, s);
refresh();
current_ctx.begin_point = null;
current_ctx.end_point = null;
}
//}}}
function draw_move(event) {//{{{
var point = trans({x:event.offsetX, y:event.offsetY});
conf("config", "point", parseInt(point.x)+","+parseInt(point.y));
if (current_ctx.agent.isMobile) {
return
}
var color = conf("config", "color");
var stroke = conf("config", "stroke");
var shape = conf("config", "shape");
if (current_ctx.begin_point) {
switch (conf("config", "shape")) {
case "move":
var m = draw.getTransform()
draw.translate(point.x-current_ctx.begin_point.x,point.y-current_ctx.begin_point.y);
refresh();
draw.setTransform(m)
break
default:
refresh();
draws(draw, {
shape: shape, stroke: stroke, color: color,
begin_point: current_ctx.begin_point,
end_point: point,
text: "",
});
}
}
}
//}}}
function add_history(his, s) {//{{{
s.index = draw_history.length;
switch (s.shape) {
case "move":
s.type = "image"
}
draw_history.push(s);
if (s.begin_point) {
var begin_x = s.begin_point.x;
var begin_y = s.begin_point.y;
var end_x = s.end_point.x;
var end_y = s.end_point.y;
}
var tr = his.appendChild(document.createElement("tr"))
var headers = ["shape", "stroke", "color", "x1", "y1", "x2", "y2", "text"]
var fields = [s.shape, s.stroke, s.color,
parseInt(begin_x), parseInt(begin_y), parseInt(end_x), parseInt(end_y), s.text]
for (var i in fields) {
var td = tr.appendChild(document.createElement("td"));
switch (headers[i]) {
case "color":
case "stroke":
case "shape":
var select = td.appendChild(document.createElement("select"));
var list = current_ctx.config[headers[i]].list;
for (var j in list) {
var option = select.appendChild(document.createElement("option"));
option.value = list[j].value;
option.text = list[j].text;
if (option.value == fields[i]) {
select.selectedIndex = j;
}
}
(function() {
var index = headers[i];
select.onchange = function(event) {
draw_history[tr.rowIndex][index] = event.target[event.target.selectedIndex].value;
refresh();
}
})();
break
default:
var input = td.appendChild(document.createElement("input"));
input.value = fields[i];
input.style.width="46px";
(function() {
var row = draw_history[tr.rowIndex]
var col = headers[i]
input.onblur = input.onkeyup = function(event) {
if (event.key && event.key != "Enter") {
return
}
var value = event.target.value;
switch (col) {
case "x1":
row.begin_point.x = value;
break
case "y1":
row.begin_point.y = value;
break
case "x2":
row.end_point.x = value;
break
case "y2":
row.end_point.y = value;
break
default:
row[data.col] = value;
}
refresh()
}
})()
}
}
his.scrollTop+=100;
return s;
}
//}}}
function refresh(time, i, last, done) {//{{{
i = i || 0
if (!last || last > draw_history.length) {
last = draw_history.length;
}
if (time) {
if (i < last) {
draws(draw, draw_history[i]);
if (draw_history[i].type == "image") {
refresh(0, 0, i);
}
setTimeout(function(){refresh(time, i, last, done)}, draw_history[i].time||time);
i++
return
}
typeof done == "function" && done();
return
}
for (i = i || 0; i < last; i++) {
if (draw_history[i].type != "image") {
draws(draw, draw_history[i]);
}
}
}
//}}}
function draws(draw, h) {//{{{
if (h.begin_point) {
var begin_x = h.begin_point.x;
var begin_y = h.begin_point.y;
var end_x = h.end_point.x;
var end_y = h.end_point.y;
}
switch (h.shape) {
case "init":
case "move":
draw.translate(end_x-begin_x, end_y-begin_y);
var m = draw.getTransform();
conf("config", "offsetX", m.e)
conf("config", "offsetY", m.f)
return
}
draw.save();
if (h.color) {
if (h.stroke == "stroke") {
draw.strokeStyle = h.color;
} else {
draw.fillStyle = h.color;
}
}
switch (h.shape) {
case "hide":
draw.clearRect(-conf("config", "offsetX")/conf("config", "scale"), -conf("config", "offsetY")/conf("config", "scale"), 400/conf("config", "scale"), 400/conf("config", "scale"));
break
case 'heart':
r = Math.sqrt(Math.pow(begin_x-end_x, 2)+Math.pow(begin_y-end_y,2));
a = Math.atan((end_y-begin_y)/(end_x-begin_x))/Math.PI*180;
drawHeart(draw, begin_x, begin_y, r, a, h.color, h.stroke)
break
case 'cycle':
draw.beginPath();
r = Math.sqrt(Math.pow(begin_x-end_x, 2)+Math.pow(begin_y-end_y,2));
draw.arc(begin_x, begin_y, r, 0, 2*Math.PI)
draw[h.stroke]()
break
case 'line':
draw.beginPath();
draw.moveTo(begin_x, begin_y);
draw.lineTo(end_x, end_y);
draw[h.stroke]()
break
case 'rect':
draw[h.stroke+"Rect"](begin_x, begin_y, end_x-begin_x, end_y-begin_y);
break
case 'text':
draw.font = current_ctx.font;
draw[h.stroke+"Text"](h.text, begin_x, begin_y, end_x-begin_x);
}
draw.restore();
}
//}}}
init(current_ctx.config, current_ctx.command);
action(null, "heart", "cmd_shape");
action(null, "red", "cmd_color");