从1号写到2号了- - 上午本来是在写一个小项目的文档,大致是这么个样子
1. xxx xxx xxx
2. xxx xxx xxx
3. xxx,xxx条件到 3.1,xxx条件到3.2
3.1 xxx
3.2 xxx 结束
4. xxx
一想,这算是流程图?感觉如果能顺手转换成流程图会很不错 但是写的时候 3.1,3.2 是 3 的分支,其实跟 3 作为主线的下一个节点 4 其实是一层,于是我把 3.1,3.2改成了 4.1,4.2 然后这样就很微妙了 1,2,3 这样表示主分支,带小数表示分支。然后这样每个节点正好对应网格中一个位置。写文字的时候如果有分支需要手动指定,不指定的话默认进入下一层主分支。之后只要确定从某点到某点的画法就好了。
对于每个图形,有固定的连接点用来连线
/*
列.行 -> 坐标
'm.n' -> row = m, col = n
'm' -> row = m, col = 0
*/
var pos = function () {
var args = Array.prototype.slice.call(arguments),
pos = [],
mw = config.minWidth,
mh = config.minHeight,
rs = config.rowSpacing,
cs = config.colSpacing,
pt = config.top,
pl = config.left,
pr = config.right,
pb = config.bottom,
args = args.join(".").split(".");
((r = +args[0]),
(c = +args[1] || +0),
(x = pl + c * (mw + cs)),
(y = pt + r * (mh + rs)),
(pos = [r, c]));
return {
x: x,
y: y,
row: r,
col: c,
id: pos,
cen: [x + mw / 2, y + mh / 2],
top: [x + mw / 2, y],
bottom: [x + mw / 2, y + mh],
left: [x, y + mh / 2],
right: [x + mw, y + mh / 2],
up: [x + mw / 2, y - rs / 2],
down: [x + mw / 2, y + rs / 2],
};
};
这个函数会传入一个或两个参数,格式可能是数字或者字符串,字符串可能带小数部分也可能不带,所以拿 参数靠解析 arguments 获得。然后之前做笔试题的时候发现这东西输出之后居然是个对象,但是在 chrome 里输出“长得像”数组,后面的 document.querySelectorAll 也类似,搜了一下找到处理办法:
关于 arguments arguments 对象并不是一个真正的Array。它类似于数组,但没有数组所特有的属性和方法,除了 length。例如,它没有 pop 方法。不过可以将其转换成数组:
var args = Array.prototype.slice.call(arguments);
现在可以获得(行,列)对应的图形的各个连接点的坐标了。然后只要在两点之间画线就好了,写个函数分别处理各种情况,由上到下怎么办,左到右,右到左,左上右下等等 …
var line = function (p0, p1) {
ctx.beginPath();
if (p0.x < p1.x && p0.y == p1.y) {
/* 左到右 */
arrow(p1.left, 1);
ctx.moveTo(...p0.right);
ctx.lineTo(...p1.left);
} else if (p0.x > p1.x && p0.y == p1.y) {
/* 左到右 */
arrow(p1.right, 3);
ctx.moveTo(...p0.left);
ctx.lineTo(...p1.right);
} else if (p0.x == p1.x && p0.y < p1.y) {
/* 从上到下 */
arrow(p1.top, 2);
ctx.moveTo(...p0.bottom);
ctx.lineTo(...p1.top);
} else if (p0.x == p1.x && p0.y > p1.y) {
/* 从下到上 */
var pt1 = pos(p0.row, p0.col + 1),
pt2 = pos(p1.row, p0.col + 1);
arrow(p1.bottom, 0);
ctx.moveTo(...p0.right);
ctx.lineTo(...pt1.cen);
ctx.lineTo(...pt2.cen);
ctx.lineTo(...p1.right);
} else if (p0.x > p1.x && p0.y > p1.y) {
/* 从右下到左上 */
var pt = pos(p1.row, p0.col);
arrow(p1.right, 3);
ctx.moveTo(...p0.top);
ctx.lineTo(...pt.cen);
ctx.lineTo(...p1.right);
} else if (p0.x < p1.x && p0.y < p1.y) {
/* 左上 - 右下 */
var pt = pos(p0.row, p1.col);
arrow(p1.top, 2);
ctx.moveTo(...p0.right);
ctx.lineTo(...pt.cen);
ctx.lineTo(...p1.top);
} else if (p0.x > p1.x && p0.y < p1.y) {
/* 右上 - 左下 */
var pt1 = [p0.cen[0], p0.bottom[1] + config.rowSpacing / 2],
pt2 = [p1.cen[0], p0.bottom[1] + config.rowSpacing / 2];
arrow(pt2, 3);
ctx.moveTo(...p0.bottom);
ctx.lineTo(...pt1);
ctx.lineTo(...pt2);
ctx.lineTo(...p1.top);
}
ctx.stroke();
};
展开运算符 很好用。
功能实现之后就该配置了,写了一堆 input。要挨个获取值么?能不能搞个数据绑定,找了下相关的文章。
数据劫持: vue.js 则是采用数据劫持结合发布者-订阅者模式的方式,通过Object.defineProperty()来劫持各个属性的setter,getter,在数据变动时发布消息给订阅者,触发相应的监听回调。 From: 剖析Vue原理&实现双向绑定MVVM
我没有往下细看,直接去了 MDN 找相关文档
get 一个给属性提供 getter 的方法,如果没有 getter 则为 undefined。该方法返回值被用作属性值。默认为 undefined。 set 一个给属性提供 setter 的方法,如果没有 setter 则为 undefined。该方法将接受唯一参数,并将该参数的新值分配给该属性。默认为 undefined。 From: Object.defineProperty() - JavaScript | MDN
Chrome 有 setAttribute 和 getAttribute,然后加上这篇文章,CSS属性选择器驱动的过滤搜索技术 « 张鑫旭-鑫空间-鑫生活
,于是我放心的给 input 加了 fc-bind="config.left" 这样的属性。现在我可以用 document.querySelectorAll('[fc-bind]') 选择所有需要绑定的元素了。
嗯?document.querySelectorAll 好像太长了
var els = document.querySelectorAll;
/* 报错!? */
var els = function (str) {
document.querySelectorAll(str);
};
/* 报错!? */
Google 一下:
querySelectoris not a generic method, it will not accept another this value. So, if you want a shortcut, you must make sure your querySelector is bound to the document:
var qs = document.querySelector.bind( document );From: javascript - Illegal invocation with document.querySelector - Stack Overflow
好吧 …
const els = document.querySelectorAll.bind(document);
var bs = Array.prototype.slice.call(els("[fc-bind]"));
var fc = {};
var fcBind = function (obj, prop, el) {
Object.defineProperty(obj, prop.toString(), {
get: function () {
var val = el.value;
if (/^#/.test(val)) {
return val;
} else if (/^\d*$/.test(val)) {
return parseInt(val);
} else {
return val;
}
},
set: function (val) {
el.value = val;
},
});
};
bs.map(function (one, id) {
var toDo = one.getAttribute("fc-bind");
var items = toDo.split(".");
t = fc;
items.map((item, id) => {
t[item] = t[item] || {};
t = t[item];
if (id == items.length - 2) {
fcBind(t, items[id + 1].toString(), one);
}
});
});
差不多就是这样
另外关于文字列表,参考中文字体网页开发指南 - 阮一峰的网络日志