1
0
mirror of https://shylinux.com/x/volcanos synced 2025-04-26 01:04:06 +08:00

opt draw.js

This commit is contained in:
harveyshao 2022-11-10 15:22:33 +08:00
parent 0cc0dbc2df
commit 172b2174f6
6 changed files with 133 additions and 230 deletions

View File

@ -10,6 +10,7 @@ Volcanos(chat.ONIMPORT, {_init: function(can, msg, cb, target) { can.onmotion.cl
}, },
_story: function(can, msg, display) { return can.onappend.plugin(can, {msg: msg, mode: chat.OUTPUT, display: can.misc.MergePath(can, display, chat.PLUGIN_STORY)}) }, _story: function(can, msg, display) { return can.onappend.plugin(can, {msg: msg, mode: chat.OUTPUT, display: can.misc.MergePath(can, display, chat.PLUGIN_STORY)}) },
"折线图": function(can, msg, field) { return can.onimport._story(can, msg, can.base.MergeURL("trend.js", {field: field, view: "折线图"})) }, "折线图": function(can, msg, field) { return can.onimport._story(can, msg, can.base.MergeURL("trend.js", {field: field, view: "折线图"})) },
"柱状图": function(can, msg, field) { return can.onimport._story(can, msg, can.base.MergeURL("trend.js", {field: field, view: "柱状图"})) },
"比例图": function(can, msg, field) { return can.onimport._story(can, msg, can.base.MergeURL("pie.js", {field: field})) }, "比例图": function(can, msg, field) { return can.onimport._story(can, msg, can.base.MergeURL("pie.js", {field: field})) },
}, [""]) }, [""])
Volcanos(chat.ONFIGURE, { Volcanos(chat.ONFIGURE, {

View File

@ -53,15 +53,15 @@ Volcanos(chat.ONIMPORT, {_init: function(can, msg, target) { can.onmotion.clear(
can._plugins = (can._plugins||[]).concat(sub) can._plugins = (can._plugins||[]).concat(sub)
}, can.ui.display): can.onimport.layout(can) }, can.ui.display): can.onimport.layout(can)
}, },
block: function(can, type, value, group) { group = group||can.group||can.svg block: function(can, type, value, group) { group = group||can.group
var target = document.createElementNS("http://www.w3.org/2000/svg", type) var target = document.createElementNS("http://www.w3.org/2000/svg", type)
return group.appendChild(can.onimport._block(can, target)), target.Value(value), target return group.appendChild(can.onimport._block(can, target)), target.Value(value), target
}, },
group: function(can, name, value, group) { var target = can.onimport.block(can, svg.G, value, group) group: function(can, name, value, group) { var target = can.onimport.block(can, svg.G, value, group||can.svg)
return target.Value(html.CLASS, name), can.onimport._group(can, target).click(), target return target.Value(html.CLASS, name), can.onimport._group(can, target).click(), target
}, },
draw: function(event, can, value, group) { draw: function(can, value, group) { group = group||can.svg
var figure = can.onfigure[value.shape], data = figure.draw(event, can, value.points, value.style||{}); can.core.Item(value.style, function(key, value) { data[key] = value }) var figure = can.onfigure[value.shape], data = figure.draw({}, can, value.points, value.style||{}); can.core.Item(value.style, function(key, value) { data[key] = value })
var target = can.onimport.block(can, figure.data.name||value.shape, data, group); can.core.ItemCB(value, function(key, cb) { target[key] = cb }) var target = can.onimport.block(can, figure.data.name||value.shape, data, group); can.core.ItemCB(value, function(key, cb) { target[key] = cb })
return value._init && value._init(target), target return value._init && value._init(target), target
}, },

View File

@ -1,42 +1,26 @@
Volcanos(chat.ONIMPORT, {help: "导入数据", _init: function(can, msg, cb, target) { can.onmotion.clear(can) Volcanos(chat.ONIMPORT, {_init: function(can, msg, cb, target) {
var color = [cli.RED, cli.YELLOW, cli.GREEN, cli.CYAN, cli.BLUE, cli.PURPLE] can.requireDraw(function() {
var color = ["#3300FF", "#2196F3", "#4CAF50", "#CDDC39", "#FFEB3B", "#9C27B0", "#795548", "#607D8B", "#CC33FF"] can.onimport.layout(can), can.onmotion.clear(can, can.ui.project), can.onmotion.toggle(can, can.ui.project, true)
var height = msg.Option(html.HEIGHT)||can.ConfHeight()
msg = can.sup.__msg||msg
can.page.ClassList.add(can, can._fields, "draw"), can.onmotion.hidden(can, can._action)
can.require(["/plugin/local/wiki/draw.js", "/plugin/local/wiki/draw/path.js"], function() { can.onimport._show(can, msg)
var margin = height/8, r = height/2-margin; can.svg.Val(html.WIDTH, 2*(r+margin)), can.svg.Val(html.HEIGHT, 2*(r+margin))
can.onimport._draw(can, msg, can.Conf(mdb.FIELD), color, r+margin, r+margin, r, margin, 0)
can.page.style(can, can.ui.project, html.MAX_WIDTH, can.ConfWidth()-height)
can.onmotion.clear(can, can.ui.project), can.onmotion.toggle(can, can.ui.project, true)
can.onappend.table(can, msg, null, can.ui.project), can.page.Select(can, can.ui.project, html.TR, function(tr, index) { can.onappend.table(can, msg, null, can.ui.project), can.page.Select(can, can.ui.project, html.TR, function(tr, index) {
can.page.Modify(can, tr, {onmouseenter: function(event) { can.onimport._draw(can, msg, can.Conf(mdb.FIELD), color, r+margin, r+margin, r, margin, index-1) }}) can.page.Modify(can, tr, {onmouseenter: function(event) { can._draw(index-1) }})
}) }), can.base.isFunc(cb) && cb(msg), can.onappend._status(can, [].concat(msg.append, ["weight"]))
can.base.isFunc(cb) && cb(msg), can.onappend._status(can, [].concat(msg.append, ["weight"]))
}) })
}, },
_draw: function(can, msg, field, color, x, y, r, margin, which) { field = field||mdb.VALUE _draw: function(can, msg, field, color, x, y, r, margin, which) { if (which == can._last) { return } can._last = which, field = field||mdb.VALUE
if (msg.Length() == 1) { return can.onimport.draw(can, {shape: svg.CIRCLE, point: [{x: x, y: y}, {x: x, y: y+r}], style: {fill: color[0]}}) }
function pos(x, y, r, angle) { angle -= 90; return [x + r * Math.cos(angle * Math.PI / 180), y + r * Math.sin(angle * Math.PI / 180)] } function pos(x, y, r, angle) { angle -= 90; return [x + r * Math.cos(angle * Math.PI / 180), y + r * Math.sin(angle * Math.PI / 180)] }
function pie(x, y, r, begin, span, color, cb) { can.onimport.draw({}, can, {shape: svg.PATH, style: kit.Dict( function pie(x, y, r, begin, span, color, cb) { can.onimport.draw(can, {shape: svg.PATH, style: kit.Dict(
svg.STROKE_WIDTH, 1, svg.STROKE, color, svg.FILL, color, "d", can.base.joins([ svg.STROKE, color, svg.FILL, color, "d", can.base.joins([
["M", x, y], ["L"].concat(pos(x, y, r, begin)), ["A", r, r, "0", span>180? "1": "0", "1"].concat(pos(x, y, r, begin+span)), ["Z"] ["M", x, y], ["L"].concat(pos(x, y, r, begin)), ["A", r, r, "0", span>180? "1": "0", "1"].concat(pos(x, y, r, begin+span)), ["Z"]
], ice.SP, ice.FS), ], ice.SP, ice.FS),
), onmouseenter: function(event) { can.base.isFunc(cb) && cb(event) } }) } ), onmouseenter: function(event) { can.base.isFunc(cb) && cb(event) } }) }
if (which == can._last) { return } can._last = which
can.onmotion.clear(can, can.svg), can.svg.Value(mdb.COUNT, 0) can.onmotion.clear(can, can.svg), can.svg.Value(mdb.COUNT, 0)
var total = 0; msg.Table(function(value) { total += can.onimport._parseInt(can, value[field]) }) var total = 0; msg.Table(function(value) { total += can.onimport._parseInt(can, value[field]) })
var begin = 0; msg[cli.COLOR] = [], msg["weight"] = [], msg.Table(function(value, index) { var span = can.onimport._parseInt(can, value[field])/total*360 var begin = 0; msg[cli.COLOR] = [], msg["weight"] = [], msg.Table(function(value, index) { var span = can.onimport._parseInt(can, value[field])/total*360
var p = index==which? pos(x, y, margin, begin+span/2): [x, y], c = color[index%color.length] var p = index==which? pos(x, y, margin, begin+span/2): [x, y], c = color[index%color.length]
pie(p[0], p[1], r, begin, span, c, function(event) { can.onimport._draw(can, msg, field, color, x, y, r, margin, index) }), begin += span
if (msg.Length() == 1) { msg.Push(cli.COLOR, '<span style="background-color:'+c+'"> </span>').Push("weight", parseInt(span*100/360)+"%")
can.onimport.draw({}, can, {shape: svg.CIRCLE, point: [{x: x, y: y}, {x: x, y: y+r}], style: {fill: color[0]}})
} else {
pie(p[0], p[1], r, begin, span, c, function(event) { can.onimport._draw(can, msg, field, color, x, y, r, margin, index) }), begin += span
}
msg.Push(cli.COLOR, '<span style="background-color:'+c+'"> </span>')
msg.Push("weight", parseInt(span*100/360)+"%")
if (index == which) { can.Status(value), can.Status("weight", parseInt(span*100/360)+"%") } if (index == which) { can.Status(value), can.Status("weight", parseInt(span*100/360)+"%") }
}) })
}, },
@ -46,6 +30,10 @@ Volcanos(chat.ONIMPORT, {help: "导入数据", _init: function(can, msg, cb, tar
if (can.base.endWith(value, "g")) { return parseInt(value)*1000000000 } if (can.base.endWith(value, "g")) { return parseInt(value)*1000000000 }
if (can.base.endWith(value, "m")) { return parseInt(value)*1000000 } if (can.base.endWith(value, "m")) { return parseInt(value)*1000000 }
return parseInt(value) return parseInt(value)
} },
layout: function(can) { var color = ["#3300FF", "#2196F3", "#4CAF50", "#CDDC39", "#FFEB3B", "#9C27B0", "#795548", "#607D8B", "#CC33FF"]
var height = can.base.Max(can.ConfHeight(), can.ConfWidth()), margin = 20, r = height/2-margin; can.svg.Val(html.WIDTH, height), can.svg.Val(html.HEIGHT, height)
can._draw = function(which) { can.onimport._draw(can, can._msg, can.Conf(mdb.FIELD), color, r+margin, r+margin, r, margin, which) }, can._draw(0)
can.page.style(can, can.ui.project, html.MAX_WIDTH, can.ConfWidth()-height)
},
}) })
Volcanos(chat.ONEXPORT, {help: "导出数据", _show: function(can) {}})

View File

@ -1,129 +1,65 @@
Volcanos(chat.ONIMPORT, {help: "导入数据", _init: function(can, msg, cb, target) { Volcanos(chat.ONIMPORT, {_init: function(can, msg, cb) {
can.onmotion.clear(can); if (msg.Length() == 0) { return } can.requireDraw(function() { can.ConfDefault({field: msg.append[0], split: ice.PS})
can.dir_root = can.Conf(nfs.ROOT)||msg.Option(nfs.DIR_ROOT), can._tree = can.onimport._tree(can, msg.Table(), can.Conf(mdb.FIELD), can.Conf(lex.SPLIT))
can.ConfDefault({root: "ice", field: msg.append[0], split: ice.PS})
can.dir_root = msg.Option(nfs.DIR_ROOT)||can.Conf("root")
can._tree = can.onimport._tree(can, msg.Table(), can.Conf(mdb.FIELD), can.Conf(lex.SPLIT))
if (!can._tree[""]) { return } can._tree[""].name = can.Conf("root")
can.size = parseInt(can.Action("size")||24)
can.margin = parseInt(can.Action("margin")||30)
can.page.ClassList.add(can, can._fields, "draw")
can.require(["/plugin/local/wiki/draw.js", "/plugin/local/wiki/draw/path.js"], function() {
can.base.isFunc(cb) && cb(msg), can.onimport.layout(can) can.base.isFunc(cb) && cb(msg), can.onimport.layout(can)
}) })
}, },
_tree: function(can, list, field, split) { _tree: function(can, list, field, split) {
var node = {}; can.core.List(list, function(item) { if (!item[field]) { return } var node = {}; can.core.List(list, function(item) { can.core.List(item[field].split(split), function(value, index, array) {
can.core.List(can.base.trimPrefix(item[field], can.dir_root+split).split(split), function(value, index, array) { var last = array.slice(0, index).join(split)||can.dir_root, name = array.slice(0, index+1).join(split)
var last = array.slice(0, index).join(split)||"", name = array.slice(0, index+1).join(split) value && !node[name] && (node[last] = node[last]||{name: last, meta: {}, list: []}).list.push(node[name] = {
if (!value || node[name]) { return } name: value+(index==array.length-1? "": split), file: item[field]||item.file, hide: true, meta: item, list: [], last: node[last],
node[last] = node[last]||{name: last, meta: {}, list: []}
node[last].list.push(node[name] = {
name: value+(index==array.length-1? "": split),
meta: item, list: [], last: node[last],
file: item[field]||item.file, hide: true,
})
}) })
}) }) }); return node
return node
}, },
_height: function(can, tree, deep) { if (!tree) { return 0 } _height: function(can, tree, deep) { tree.deep = deep||0, tree.height = 0; if (tree.list.length == 0 || tree.hide) { return tree.height = 1 }
tree.deep = deep||0 can.core.List(tree.list, function(item) { tree.height += can.onimport._height(can, item, (deep||0)+1) }); return tree.height
if (!tree.list || tree.list.length == 0 || tree.hide) { return tree.height = 1 }
var height = 0; can.core.List(tree.list, function(item) {
height += can.onimport._height(can, item, (deep||0)+1)
})
return tree.height = height
}, },
_width: function(can, tree, deep) { if (!tree) { return 0 } _width: function(can, tree, deep) { tree.deep = deep||0, tree.width = 0; if (tree.list.length == 0 || tree.hide) {
tree.deep = deep||0 return tree.width = can.onimport.draw(can, {shape: html.TEXT, points: [{x: 0, y: 0}], style: {inner: tree.name}}).Val(svg.TEXT_LENGTH)+can.margin
if (!tree.list || tree.list.length == 0 || tree.hide) { if (!tree.name) { return tree.width = 20 } } can.core.List(tree.list, function(item) { tree.width += can.onimport._width(can, item, (deep||0)+1) }); return tree.width
tree.view = can.onimport.draw({}, can, {shape: html.TEXT, point: [{x: 0, y: 0}], style: {inner: tree.name}})
return tree.width = tree.view.Val("textLength")+can.margin
}
var width = 0; can.core.List(tree.list, function(item) {
width += can.onimport._width(can, item, (deep||0)+1)
})
return tree.width = width
}, },
_color: function(can, tree) { _color: function(can, tree) { return tree.meta.color || (tree.list == 0? cli.PURPLE: cli.YELLOW) },
return tree.meta&&tree.meta.color || (tree.list == 0? cli.PURPLE: cli.YELLOW) layout: function(can) { can.page.style(can, can._output, html.MAX_HEIGHT, "")
}, can.svg.Val(svg.FONT_SIZE, can.size = parseInt(can.Action(html.SIZE))), can.margin = parseInt(can.Action(html.MARGIN))
layout: function(can) { can.margin = can.margin||20
can.onmotion.clear(can), can.onimport._show(can, can.request())
can.svg.Val(svg.FONT_SIZE, can.Action("size"))
can.page.style(can, can._output, html.MAX_HEIGHT, "")
can.onaction[can.Action(ice.VIEW)](event, can, can.Action(ice.VIEW)) can.onaction[can.Action(ice.VIEW)](event, can, can.Action(ice.VIEW))
}, },
}, [""]) }, [""])
Volcanos(chat.ONACTION, {help: "用户操作", list: [ Volcanos(chat.ONACTION, {list: [[ice.VIEW, "横向", "纵向"], [html.SIZE, 24, 32, 48], [html.MARGIN, 10, 30, 50]],
[ice.VIEW, "横向", "纵向"], ["size", 24, 32, 48], ["margin", 30, 50, 100], size: function(event, can) { can.onimport.layout(can) }, margin: function(event, can) { can.onimport.layout(can) },
], "横向": function(event, can, button) { can.onimport._height(can, can._tree[can.dir_root]), can.onmotion.clear(can, can.svg)
size: function(event, can) { can.size = parseInt(can.Action("size")||30), can.onimport.layout(can) }, can.svg.Val(html.HEIGHT, can._tree[can.dir_root].height*(can.size+can.margin)+2*can.margin), can.svg.Value(svg.TEXT_ANCHOR, "start")
margin: function(event, can) { can.margin = parseInt(can.Action("margin")||30), can.onimport.layout(can) }, can.onaction._draw_horizontal(can, can._tree[can.dir_root], can.margin, can.margin)
"横向": function(event, can, button) {
can.onimport._height(can, can._tree[""])
can.sup.view = button, can.onmotion.clear(can, can.svg)
can.svg.Val(html.HEIGHT, can._tree[""].height*can.margin+2*can.margin)
can.width = 0, can.onaction._draw_horizontal(can, can._tree[""], can.margin, can.margin)
can.svg.Val(html.WIDTH, can.width+can.margin)
}, },
"纵向": function(event, can, button) { "纵向": function(event, can, button) { can.onimport._width(can, can._tree[can.dir_root]), can.onmotion.clear(can, can.svg)
can.onimport._width(can, can._tree[""]) can.svg.Val(html.WIDTH, can._tree[can.dir_root].width+2*can.margin), can.svg.Value(svg.TEXT_ANCHOR, "middle")
can.sup.view = button, can.onmotion.clear(can, can.svg) can.onaction._draw_vertical(can, can._tree[can.dir_root], can.margin, can.margin+(can.size+can.margin)/2)
can.svg.Val(html.WIDTH, can._tree[""].width+2*can.margin)
can.height = 0, can.onaction._draw_vertical(can, can._tree[""], can.margin, can.margin+can.margin)
can.svg.Val(html.HEIGHT, can.height+can.margin)
}, },
_draw: function(can, tree, x, y, style) { var color = can.onimport._color(can, tree) _draw: function(can, tree, x, y, style) { var color = can.onimport._color(can, tree)
if (!tree.name) { return } tree.view = can.onimport.draw(can, {shape: html.TEXT, points: [{x: x, y: y}], style: can.base.Copy(kit.Dict(svg.STROKE, color, svg.FILL, color, html.INNER, tree.name), style)})
tree.view = can.onimport.draw({}, can, {shape: html.TEXT, point: [{x: x, y: y}], style: can.base.Copy(kit.Dict( return can.core.ItemCB(can.ondetail, tree.view, can, tree), tree.view
svg.STROKE, color, svg.FILL, color, svg.TEXT_ANCHOR, "start", "inner", tree.name||tree.file,
), style), }), can.core.ItemCB(can.ondetail, tree.view, can, tree)
}, },
_draw_vertical: function(can, tree, x, y) { tree.x = x, tree.y = y _draw_vertical: function(can, tree, x, y) {
can.onaction._draw(can, tree, x+tree.width/2, y, kit.Dict(svg.TEXT_ANCHOR, "middle")) tree.height = can.size+can.margin, can.onaction._draw(can, tree, tree.x = x+tree.width/2, tree.y = y); if (y+tree.height > can.svg.Val(html.HEIGHT)) { can.svg.Val(html.HEIGHT, y+tree.height) }
var offset = 0; tree.hide || can.core.List(tree.list, function(item) {
tree.height = can.margin can.onimport.draw(can, {shape: svg.PATH2V, points: [
if (y+tree.height > can.height) { can.height = y+tree.height } {x: x+tree.width/2, y: y+tree.height/2-can.margin/2}, {x: x+offset+item.width/2, y: y+tree.height/2+8*can.margin-can.margin/2},
if (tree.hide) { return } ], style: {stroke: cli.CYAN}}), can.onaction._draw_vertical(can, item, x+offset, y+tree.height+8*can.margin), offset += item.width
var offset = 0; can.core.List(tree.list, function(item) { if (!item) { return }
item.name && item.name != " " && can.onimport.draw({}, can, {shape: svg.PATH2V, point: [
{x: x+tree.width/2, y: y+tree.height-can.margin/2},
{x: x+offset+item.width/2, y: y+tree.height+can.margin/2},
], style: {stroke: cli.CYAN}})
can.onaction._draw_vertical(can, item, x+offset, y+tree.height+can.margin), offset += item.width
}) })
}, },
_draw_horizontal: function(can, tree, x, y) { tree.x = x, tree.y = y _draw_horizontal: function(can, tree, x, y) {
can.onaction._draw(can, tree, x, y+tree.height*can.margin/2, kit.Dict(svg.TEXT_ANCHOR, "start")) tree.width = can.onaction._draw(can, tree, tree.x = x, tree.y = y+tree.height*(can.size+can.margin)/2).Val(svg.TEXT_LENGTH); if (x+tree.width > can.svg.Val(html.WIDTH)) { can.svg.Val(html.WIDTH, x+tree.width) }
var offset = 0; tree.hide || can.core.List(tree.list, function(item) {
tree.width = tree.view&&tree.view.Val("textLength")||(tree.name||"").length*10 can.onimport.draw(can, {shape: svg.PATH2H, points: [
if (x+tree.width > can.width) { can.width = x+tree.width } {x: x+tree.width+can.margin/2, y: y+tree.height*(can.size+can.margin)/2}, {x: x+tree.width+8*can.margin-can.margin/2, y: y+offset+item.height*(can.size+can.margin)/2}
if (tree.hide) { return } ], style: {stroke: cli.CYAN}}), can.onaction._draw_horizontal(can, item, x+tree.width+8*can.margin, y+offset), offset += item.height*(can.size+can.margin)
var offset = 0; can.core.List(tree.list, function(item) { if (!item || !item.name) { return }
can.onimport.draw({}, can, {shape: svg.PATH2H, point: [
{x: x+tree.width+can.margin/8, y: y+tree.height*can.margin/2},
{x: x+tree.width+can.margin*2-2*can.margin/8, y: y+offset+item.height*can.margin/2}
], style: {stroke: cli.CYAN}})
can.onaction._draw_horizontal(can, item, x+tree.width+2*can.margin, y+offset)
offset += item.height*can.margin
}) })
}, },
}) })
Volcanos(chat.ONDETAIL, {help: "用户交互", Volcanos(chat.ONDETAIL, {
onmouseenter: function(event, can, tree) { var y = tree.y+tree.height*can.margin/2 onmouseenter: function(event, can, tree) { var view = tree.view, width = can.Action(ice.VIEW) == "纵向"? view.Val(svg.TEXT_LENGTH)/2: 0
can.page.Remove(can, can.pos), can.pos = can.onimport.draw({}, can, {shape: svg.RECT, point: [ can.page.Remove(can, can.pos), can.pos = can.onimport.draw(can, {shape: svg.RECT, points: [
{x: tree.x-can.margin/4, y: y-can.margin/2}, {x: tree.x+tree.width+can.margin/8, y: y+can.margin/2}, {x: view.Val(svg.X)-width-can.margin/2, y: view.Val(svg.Y)-(can.size+can.margin/2)/2}, {x: view.Val(svg.X)-width+view.Val(svg.TEXT_LENGTH)+can.margin/2, y: view.Val(svg.Y)+(can.size+can.margin/2)/2},
], style: {stroke: cli.RED, fill: html.NONE}}), can.onkeymap.prevent(event) ], style: {stroke: cli.RED, fill: html.NONE}}), can.onkeymap.prevent(event)
}, },
onclick: function(event, can, tree) { onclick: function(event, can, tree) {
@ -138,7 +74,7 @@ Volcanos(chat.ONDETAIL, {help: "用户交互",
if (msg.Append(mdb.INDEX)) { msg.Table(function(value) { can.ondetail.plugin(can, value.index, []) }); return } if (msg.Append(mdb.INDEX)) { msg.Table(function(value) { can.ondetail.plugin(can, value.index, []) }); return }
if (msg.Option(lex.SPLIT)) { if (msg.Option(lex.SPLIT)) {
tree.list = can.onimport._tree(can, msg.Table(), msg.Option(mdb.FIELD)||msg.append[0], msg.Option(lex.SPLIT))[""].list||[] tree.list = can.onimport._tree(can, msg.Table(), msg.Option(mdb.FIELD)||msg.append[0], msg.Option(lex.SPLIT))[can.dir_root].list||[]
can.core.List(tree.list, function(item) { item.last = tree }) can.core.List(tree.list, function(item) { item.last = tree })
} else { } else {
msg.Table(function(item) { tree.list.push({ msg.Table(function(item) { tree.list.push({
@ -151,7 +87,7 @@ Volcanos(chat.ONDETAIL, {help: "用户交互",
}, true) }, true)
}, },
plugin: function(can, index, args, prefix) { plugin: function(can, index, args, prefix) {
can.onappend.plugin(can, {type: chat.STORY, mode: chat.FLOAT, index: index, args: args}, function(sub) { can.onappend.plugin(can, {mode: chat.FLOAT, index: index, args: args}, function(sub) {
sub.run = function(event, cmds, cb) { can.runAction(can.request(event), prefix||[ice.RUN, index], cmds, cb) } sub.run = function(event, cmds, cb) { can.runAction(can.request(event), prefix||[ice.RUN, index], cmds, cb) }
sub.onaction.close = function() { can.page.Remove(can, sub._target) } sub.onaction.close = function() { can.page.Remove(can, sub._target) }
can.getActionSize(function(left, top, width, height) { left = left||0 can.getActionSize(function(left, top, width, height) { left = left||0

View File

@ -1,139 +1,111 @@
Volcanos(chat.ONIMPORT, {help: "导入数据", _init: function(can, msg, cb, target) { Volcanos(chat.ONIMPORT, {_init: function(can, msg, cb) {
can.onmotion.clear(can), can.page.ClassList.add(can, can._fields, "draw") can.requireDraw(function() {
can.require(["/plugin/local/wiki/draw.js", "/plugin/local/wiki/draw/path.js"], function() { can.data = msg.Table(), can.base.isFunc(cb) && cb(msg), can.onimport.layout(can)
can.data = msg.Table(), can.onimport._sum(can)
can.base.isFunc(cb) && cb(msg), can.Conf(ice.VIEW) && can.Action(ice.VIEW, can.Conf(ice.VIEW))
can.list = can.sup.list||can.list
can.onimport.layout(can), can.base.isFunc(cb) && cb(msg)
can.data = msg.Table(), can.onimport._sum(can)
}) })
}, },
_sum: function(can) { _sum: function(can) { if (can.list) { return can.list }
var begin = "", count = 0, rest = 0, add = 0, del = 0, max = 0 var begin = "", count = 0, rest = 0, add = 0, del = 0, max = 0
can.max = 0, can.min = 0, can.list = can.core.List(can.data, function(value, index) { can.max = 0, can.min = 0, can.list = can.core.List(can.data, function(value, index) {
var line = { var item = {
date: value[can._msg.append[0]], date: value[can._msg.append[0]],
text: value[can._msg.append[4]], text: value[can._msg.append[4]],
add: parseInt(value[can._msg.append[1]]), add: parseInt(value[can._msg.append[1]]),
del: parseInt(value[can._msg.append[2]]), del: parseInt(value[can._msg.append[2]]),
} }
line.begin = rest item.begin = rest
line.max = rest + line.add item.max = rest + item.add
line.min = rest - line.del item.min = rest - item.del
line.close = rest + line.add - line.del item.close = rest + item.add - item.del
begin = begin || value.date, count++ begin = begin || value.date, count++
rest = line.close, add += line.add, del += line.del rest = item.close, add += item.add, del += item.del
if (line.max - line.min > max) { max = line.max - line.min } if (item.max - item.min > max) { max = item.max - item.min }
if (line.max > can.max) { can.max = line.max } if (item.max > can.max) { can.max = item.max }
if (line.min < can.min) { can.min = line.min } if (item.min < can.min) { can.min = item.min }
return line return item
}) })
can.Status({"from": begin, "commit": count, "total": add+del, "max": max}) can.Status({"from": begin, "commit": count, "total": add+del, "max": max})
return can.list
}, },
_layout: function(can) { _layout: function(can) {
var height = can.onexport.height(can) var height = can.onexport.height(can), width = parseInt(can.ConfWidth())
var width = parseInt(can.ConfWidth()), space = parseInt(can.Action("space")||"10")
var step = parseFloat((width-2*space) / can.list.length)
can.onmotion.clear(can, can._output), can.onimport._show(can, can._msg) can.onmotion.clear(can, can._output), can.onimport._show(can, can._msg)
can.svg.Val(html.HEIGHT, height), can.svg.Val(html.WIDTH, width) can.svg.Val(html.HEIGHT, height), can.svg.Val(html.WIDTH, width)
return {height: height, width: width, space: space, step: step} var margin = parseInt(can.Action(html.MARGIN)), step = parseFloat((width-2*margin) / can._msg.Length())
return {height: height, width: width, margin: margin, step: step}
}, },
layout: function(can) { layout: function(can) {
can.onmotion.toggle(can, can._option, !can.user.isMobile || !can.isFullMode()) can.onmotion.toggle(can, can._option, !can.user.isMobile || !can.isFullMode())
can.Conf(ice.VIEW) && can.Action(ice.VIEW, can.Conf(ice.VIEW))
can.onaction[can.Action(ice.VIEW)]({}, can) can.onaction[can.Action(ice.VIEW)]({}, can)
}, },
transform: function(can, target) { transform: function(can, target) {
target.Value("transform", "translate(0, "+parseInt(can.ConfHeight())+") scale(1, -1)") target.Value("transform", "translate(0, "+parseInt(can.ConfHeight())+") scale(1, -1)")
}, },
}, [""]) }, [""])
Volcanos(chat.ONACTION, {help: "组件菜单", list: [ Volcanos(chat.ONACTION, {list: [
[ice.VIEW, "趋势图", "柱状图", "折线图", "数据源"], [ice.VIEW, "趋势图", "柱状图", "折线图", "数据源"],
[html.HEIGHT, ice.AUTO, 100, 200, 400, 600, 800], [html.HEIGHT, ice.AUTO, 100, 200, 400, 600, 800],
["space", 10, 20, 50, 100], [html.MARGIN, 10, 20, 50, 100],
[html.SPEED, 10, 20, 50, 100], [html.SPEED, 10, 20, 50, 100],
], ],
"折线图": function(event, can) { var args = can.onimport._layout(can) "趋势图": function(event, can) { var args = can.onimport._layout(can)
function scale(y) { return (y - can.min)/(can.max - can.min)*(args.height-2*args.margin) }
function order(index, x, y) { return {x: args.margin+args.step*index+x, y: args.height-args.margin-scale(y)} }
var black = can.onimport.group(can, cli.BLACK, kit.Dict(svg.STROKE, cli.BLACK, svg.FILL, cli.BLACK))
var white = can.onimport.group(can, cli.WHITE, kit.Dict(svg.STROKE, cli.WHITE, svg.FILL, cli.WHITE))
can.core.Next(can.onimport._sum(can), function(item, next, index) { can.core.Timer(parseInt(can.Action(html.SPEED)), next), can.Status(item)
can.onimport.draw(can, {shape: svg.LINE, points: [
order(index, args.step/2, item.min), order(index, args.step/2, item.max),
]}, item.begin < item.close? white: black)
can.onimport.draw(can, {shape: svg.RECT, points: [
order(index, args.step/4, item.close), order(index, args.step/4*3, item.begin),
], style: {rx: 0, ry:0}, _init: function(target) {
can.core.ItemCB(can.ondetail, function(key, cb) { target[key] = function(event) { cb(event, can, item) } })
}}, item.begin < item.close? white: black)
})
},
"折线图": function(event, can) { var args = can.onimport._layout(can); args.step = parseFloat((args.width-2*args.margin) / (can._msg.Length()-1))
var black = can.onimport.group(can, cli.BLACK, kit.Dict(svg.STROKE, cli.BLACK, svg.FILL, cli.BLACK)) var black = can.onimport.group(can, cli.BLACK, kit.Dict(svg.STROKE, cli.BLACK, svg.FILL, cli.BLACK))
var white = can.onimport.group(can, cli.WHITE, kit.Dict(svg.STROKE, cli.WHITE, svg.FILL, cli.WHITE)) var white = can.onimport.group(can, cli.WHITE, kit.Dict(svg.STROKE, cli.WHITE, svg.FILL, cli.WHITE))
can.onimport.transform(can, black), can.onimport.transform(can, white) can.onimport.transform(can, black), can.onimport.transform(can, white)
can.core.List(can.list, function(list) { can.core.List(can.base.Obj(can.Conf(mdb.FIELD), can._msg.append), function(field) { var max = can.data[0][field], min = can.data[0][field]
var max = list[0], min = list[0], step = (can.ConfWidth()-2*args.space)/(list.length-1) for (var i = 1; i < can.data.length; i += 1) { var value = can.data[i][field]; if (value > max) { max = value } if (value < min) { min = value } }
for (var i = 1; i < list.length; i += 1) { if (list[i] > max) { max = list[i] } if (list[i] < min) { min = list[i] } } function order(i) { return i*args.step+args.margin } function scale(y) { return (y - min)/(max - min)*(args.height-2*args.margin)+args.margin }
function scale(y) { return (y - min)/(max - min)*(args.height-2*args.space)+args.space } for (var i = 1; i < can.data.length; i += 1) {
function order(i) { return i*step+args.space } can.onimport.draw(can, {shape: svg.LINE, points: [{x: order(i-1), y: scale(can.data[i-1][field])}, {x: order(i), y: scale(can.data[i][field])}]}, white)
for (var i = 1; i < list.length; i += 1) {
can.onimport.draw({}, can, {shape: svg.LINE, point: [{x: order(i-1), y: scale(list[i-1])}, {x: order(i), y: scale(list[i])}]}, white)
} }
}) })
}, },
"趋势图": function(event, can) { var args = can.onimport._layout(can) "柱状图": function(event, can) { var args = can.onimport._layout(can)
function scale(y) { return (y - can.min)/(can.max - can.min)*(args.height-2*args.space) }
function order(index, x, y) { return {x: args.space+args.step*index+x, y: args.height-args.space-scale(y)} }
var black = can.onimport.group(can, cli.BLACK, kit.Dict(svg.STROKE, cli.BLACK, svg.FILL, cli.BLACK)) var black = can.onimport.group(can, cli.BLACK, kit.Dict(svg.STROKE, cli.BLACK, svg.FILL, cli.BLACK))
var white = can.onimport.group(can, cli.WHITE, kit.Dict(svg.STROKE, cli.WHITE, svg.FILL, cli.WHITE)) var white = can.onimport.group(can, cli.WHITE, kit.Dict(svg.STROKE, cli.WHITE, svg.FILL, cli.WHITE))
can.onimport.transform(can, black), can.onimport.transform(can, white)
can.core.Next(can.list, function(line, next, index) { can.Status(line) can.core.List(can.base.Obj(can.Conf(mdb.FIELD), can._msg.append), function(field) { var max = can.data[0][field], min = can.data[0][field]
can.onimport.draw({}, can, {shape: svg.LINE, point: [ for (var i = 1; i < can.data.length; i += 1) { var value = can.data[i][field]; if (value > max) { max = value } if (value < min) { min = value } }
order(index, args.step/2, line.min), order(index, args.step/2, line.max), function order(i) { return i*args.step+args.margin } function scale(y) { return (y - min)/(max - min)*(args.height-2*args.margin)+args.margin }
]}, line.begin < line.close? white: black) can.core.Next(can.data, function(item, next, i) { can.core.Timer(parseInt(can.Action(html.SPEED)), next)
can.onimport.draw(can, {shape: svg.RECT, style: {rx: 0, ry: 0}, points: [{x: order(i)+args.step/8.0, y: args.margin}, {x: order(i)+args.step/8.0*7, y: scale(item[field])}], _init: function(target) {
can.onimport.draw({}, can, {shape: svg.RECT, point: [ can.core.ItemCB(can.ondetail, function(key, cb) { target[key] = function(event) { cb(event, can, item) } })
order(index, args.step/4, line.close), order(index, args.step/4*3, line.begin), }}, white)
], style: {rx: 0, ry:0}, _init: function(view) {
can.core.ItemCB(can.ondetail, function(key, cb) { view[key] = function(event) { cb(event, can, line) } })
}}, line.begin < line.close? white: black)
can.core.Timer(parseInt(can.Action(html.SPEED)), next)
})
},
"柱状图": function(event, can) { var args = can.onimport._layout(can)
var max = {}, min = {}; can.core.List(can._msg.append, function(key, which) {
can.core.List(can.data, function(value, index) {
var v = parseInt(value[key])||0; if (index == 0) {
return max[key] = v, min[key] = v
}
if (v > max[key]) { max[key] = v }
if (v < min[key]) { min[key] = v }
}) })
}) })
function scale(key, y) { return (y - min[key])/(max[key] - min[key])*(args.height-2*args.space) }
var width = args.step/can._msg.append.length, which = 0
can.core.List(can._msg.append, function(key, which) { if (max[key] == min[key]) { return }
can.core.Next(can.data, function(line, next, index) { if (parseInt(line[key]) == 0) { return }
can.onimport.draw({}, can, {shape: svg.RECT, point: [
{x: args.space+args.step*index+width*which+2, y: args.height-args.space-scale(key, parseInt(line[key]))},
{x: args.space+args.step*index+width*(which+1)+2, y: args.height-args.space},
], style: kit.Dict(svg.STROKE_WIDTH, 1, svg.STROKE, cli.WHITE, svg.FILL, cli.WHITE, svg.RX, 0, svg.RY, 0), _init: function(view) {
can.core.ItemCB(can.ondetail, function(key, cb) { view[key] = function(event) { cb(event, can, line) } })
}}), can.core.Timer(parseInt(can.Action(html.SPEED)), next)
}), which++
})
},
"数据源": function(event, can) {
can.onmotion.clear(can, can._output)
can.onappend.table(can, can._msg, null, can._output)
}, },
"数据源": function(event, can) { can.onmotion.clear(can), can.onappend.table(can, can._msg) },
height: function(event, can) { can.onimport.layout(can) }, height: function(event, can) { can.onimport.layout(can) },
space: function(event, can) { can.onimport.layout(can) }, margin: function(event, can) { can.onimport.layout(can) },
speed: function(event, can) { can.onimport.layout(can) }, speed: function(event, can) { can.onimport.layout(can) },
}) })
Volcanos(chat.ONDETAIL, {help: "用户交互", Volcanos(chat.ONDETAIL, {
onmouseenter: function(event, can, line) { can.Status(line) }, onmouseenter: function(event, can, item) { can.Status(item) },
}) })
Volcanos(chat.ONEXPORT, {help: "导出数据", list: ["from", "commit", "total", "max", "date", "text", "add", "del"], Volcanos(chat.ONEXPORT, {list: ["from", "commit", "total", "max", "date", "text", "add", "del"],
height: function(can) { var height = can.Action(html.HEIGHT) height: function(can) { var height = can.Action(html.HEIGHT)
if (height == ice.AUTO) { height = can.ConfHeight() if (height == ice.AUTO) { height = can.ConfHeight() } if (height < 200) { height = 200 }
// can.isFullMode() || (height = can.base.Max(can.ConfHeight(), 600))
}
if (height < 200) { height = 200 }
return parseInt(height||can.page.height()/2) return parseInt(height||can.page.height()/2)
}, },
}) })

View File

@ -96,7 +96,7 @@ var mdb = {
var ssh = { var ssh = {
} }
var nfs = { var nfs = {
PATH: "path", FILE: "file", LINE: "line", SIZE: "size", PATH: "path", FILE: "file", LINE: "line", SIZE: "size", ROOT: "root",
SAVE: "save", LOAD: "load", FIND: "find", GREP: "grep", TAGS: "tags", SAVE: "save", LOAD: "load", FIND: "find", GREP: "grep", TAGS: "tags",
DIR: "dir", CAT: "cat", DEFS: "defs", TRASH: "trash", SCRIPT: "script", CONTENT: "content", DIR_ROOT: "dir_root", PWD: "./", DIR: "dir", CAT: "cat", DEFS: "defs", TRASH: "trash", SCRIPT: "script", CONTENT: "content", DIR_ROOT: "dir_root", PWD: "./",
HTML: "html", CSS: "css", JS: "js", GO: "go", SH: "sh", CSV: "csv", JSON: "json", HTML: "html", CSS: "css", JS: "js", GO: "go", SH: "sh", CSV: "csv", JSON: "json",
@ -197,6 +197,7 @@ var svg = {
G: "g", X: "x", Y: "y", R: "r", RX: "rx", RY: "ry", CX: "cx", CY: "cy", X1: "x1", Y1: "y1", X2: "x2", Y2: "y2", G: "g", X: "x", Y: "y", R: "r", RX: "rx", RY: "ry", CX: "cx", CY: "cy", X1: "x1", Y1: "y1", X2: "x2", Y2: "y2",
PATH: "path", PATH2V: "path2v", PATH2H: "path2h", PATH: "path", PATH2V: "path2v", PATH2H: "path2h",
M: "M", Q: "Q", T: "T", M: "M", Q: "Q", T: "T",
TEXT_LENGTH: "textLength",
} }
var html = {PLUGIN_MARGIN: 10, ACTION_HEIGHT: 31, ACTION_MARGIN: 200, var html = {PLUGIN_MARGIN: 10, ACTION_HEIGHT: 31, ACTION_MARGIN: 200,
FIELDSET: "fieldset", LEGEND: "legend", OPTION: "option", ACTION: "action", OUTPUT: "output", STATUS: "status", FIELDSET: "fieldset", LEGEND: "legend", OPTION: "option", ACTION: "action", OUTPUT: "output", STATUS: "status",
@ -212,7 +213,7 @@ var html = {PLUGIN_MARGIN: 10, ACTION_HEIGHT: 31, ACTION_MARGIN: 200,
SPAN: "span", CODE: "code", DIV: "div", IMG: "img", VIDEO: "video", SPACE: "space", SPAN: "span", CODE: "code", DIV: "div", IMG: "img", VIDEO: "video", SPACE: "space",
WSS: "wss", SVG: "svg", CANVAS: "canvas", IFRAME: "iframe", CHROME: "chrome", WSS: "wss", SVG: "svg", CANVAS: "canvas", IFRAME: "iframe", CHROME: "chrome",
CLASS: "class", DISPLAY: "display", BLOCK: "block", NONE: "none", HIDDEN: "hidden", TOGGLE: "toggle", CLASS: "class", DISPLAY: "display", BLOCK: "block", NONE: "none", HIDDEN: "hidden", TOGGLE: "toggle", SIZE: "size",
HEIGHT: "height", WIDTH: "width", PADDING: "padding", MARGIN: "margin", LEFT: "left", TOP: "top", RIGHT: "right", BOTTOM: "bottom", HEIGHT: "height", WIDTH: "width", PADDING: "padding", MARGIN: "margin", LEFT: "left", TOP: "top", RIGHT: "right", BOTTOM: "bottom",
MIN_HEIGHT: "min-height", MAX_HEIGHT: "max-height", MIN_WIDTH: "min-width", MAX_WIDTH: "max-width", MARGIN_TOP: "margin-top", MARGIN_X: "margin-x", MARGIN_Y: "margin-y", MIN_HEIGHT: "min-height", MAX_HEIGHT: "max-height", MIN_WIDTH: "min-width", MAX_WIDTH: "max-width", MARGIN_TOP: "margin-top", MARGIN_X: "margin-x", MARGIN_Y: "margin-y",
BACKGROUND: "background", OPACITY: "opacity", OVERFLOW: "overflow", SCROLL: "scroll", SPEED: "speed", FLOAT: "float", CLEAR: "clear", BOTH: "both", BACKGROUND: "background", OPACITY: "opacity", OVERFLOW: "overflow", SCROLL: "scroll", SPEED: "speed", FLOAT: "float", CLEAR: "clear", BOTH: "both",
@ -258,6 +259,11 @@ var Volcanos = shy({iceberg: "/chat/", volcano: "/frame.js", cache: {}, pack: {}
libs[i] = "/require/node_modules/"+libs[i] libs[i] = "/require/node_modules/"+libs[i]
} can.require(libs, cb, cbs) } can.require(libs, cb, cbs)
}, },
requireDraw: function(cb) { can.page.ClassList.add(can, can._fields, "draw")
can.require(["/plugin/local/wiki/draw.js", "/plugin/local/wiki/draw/path.js"], function() {
can.onmotion.clear(can), can.onimport._show(can, can._msg), cb()
})
},
require: function(libs, cb, cbs) { require: function(libs, cb, cbs) {
if (!libs || libs.length == 0) { return typeof cb == lang.FUNCTION && setTimeout(function() { cb(can) }, 10) } if (!libs || libs.length == 0) { return typeof cb == lang.FUNCTION && setTimeout(function() { cb(can) }, 10) }
if (libs[0] == undefined) { return can.require(libs.slice(1), cb, cbs) } if (libs[0] == undefined) { return can.require(libs.slice(1), cb, cbs) }