由于最近一直比较忙,所以没有更新博客
由于博主做的项目不需要舞台与模拟器的概念,所以在技术选型上也就没有选择s3等其他的图形化编程框架
今天给大家带来的是blockly自定义左侧菜单栏、以及交互效果如何去加
首先我们得了解blockly是什么?以及他提供的一些api、怎么用?
谷歌blockly官网
blockly源码
某书上看到的一个api入门介绍
看了上面做这几个之后你就能清楚的解决上面提的问题(这部分自己看,就不详细介绍了,如果有不懂得可以留言,一起研究)
接下来就可以说这篇博客要做的事了
首先看一下dom结构
发现他自己生成的就是圈起来的这样的结构,好了现在的思路就很简单了,源代码的结构与咱们的结构就只差一个icon,所以就想到既然他能生成这样的一个dom结构,我们也就可以随意的生成咱们所需要的dom,比如img元素、当然你也可以随意生成dom然后给背景图
于是大致思路就是找到源码生成左侧dom的关键代码,生成我们需要的dom
so:
goog.ui.tree.BaseNode.prototype.getLabelSafeHtml = function() {
var a = goog.html.SafeHtml.create("span", { "class": this.config_.cssItemLabel, title: this.getToolTip() || null }, this.getSafeHtml());
return goog.html.SafeHtml.concat(a, goog.html.SafeHtml.create("span", {}, this.getAfterLabelSafeHtml()))
};
这个方法就是生成咱们刚才圈起来的span的,哈哈哈 你肯定想到了咱们当然可以利用这个来创建一个img标签
so:
// add 生成img标签解析器
goog.ui.tree.BaseNode.prototype.getLabelSafeself = function() {
var a = goog.html.SafeHtml.create("image", { "class": this.config_.cssItemLabel, title: this.getToolTip(), "src": this.getCategoryImg().trueUrl || null,"backgroundData":JSON.stringify(this.getCategoryImg()) });
return goog.html.SafeHtml.concat(a, '')
};
上面这段代码做的事就是生成了一个image标签,并给了一个src属性
其中这个this.getCategoryImg()是我自己给每个类别匹配相应icon的方法,代码如下:
// 获取图片类别
goog.ui.tree.BaseNode.prototype.getCategoryImg = function() {
let style_pt = this.html_.privateDoNotAccessOrElseSafeHtmlWrappedValue_,
trueUrl = '',clickUrl='';
if (style_pt) {
switch (style_pt) {
case "逻辑":
trueUrl = "http://pic38.nipic.com/20140225/2531170_214014788000_2.jpg";
clickUrl= "http://img2.imgtn.bdimg.com/it/u=1694287427,1534841493&fm=26&gp=0.jpg";
break;
case "If":
trueUrl = "http://img2.imgtn.bdimg.com/it/u=1694287427,1534841493&fm=26&gp=0.jpg";
clickUrl= "http://img2.imgtn.bdimg.com/it/u=1694287427,1534841493&fm=26&gp=0.jpg";
break;
case "Boolean":
trueUrl = "http://img17.3lian.com/d/file/201702/14/3d1d78481dbe5db4802f4b1eb548f365.jpg";
clickUrl= "http://img2.imgtn.bdimg.com/it/u=1694287427,1534841493&fm=26&gp=0.jpg";
break;
// pt case start
case "变量":
trueUrl = "block/img/variable.png";
clickUrl= "block/img/variable_click.png";
break;
case "运动":
trueUrl = "block/img/movement.png";
clickUrl= "block/img/movement_click.png";
break;
case "IO":
trueUrl = "block/img/IO.png";
clickUrl= "block/img/IO_click.png";
break;
case "流程":
trueUrl = "block/img/process.png";
clickUrl= "block/img/process_click.png";
break;
case "文本注释":
trueUrl = "block/img/annotations.png";
clickUrl= "block/img/annotations_click.png";
break;
case "等待与暂停":
trueUrl = "block/img/wait.png";
clickUrl= "block/img/wait_click.png";
break;
case "函数":
trueUrl = "block/img/function.png";
clickUrl= "block/img/function_click.png";
break;
case "通信":
trueUrl = "block/img/communication.png";
clickUrl= "block/img/communication_click.png";
break;
case "输入输出":
trueUrl = "block/img/InputAndOutput.png";
clickUrl= "block/img/InputAndOutput_click.png";
break;
case "中断":
trueUrl = "block/img/interrupt.png";
clickUrl= "block/img/interrupt_click.png";
break;
case "运算":
trueUrl = "block/img/operation.png";
clickUrl= "block/img/operation_click.png";
break;
case "ARL":
trueUrl = "block/img/ARL.png";
clickUrl= "block/img/ARL_click.png";
break;
case "开关":
trueUrl = "block/img/switch.png";
clickUrl= "block/img/switch_click.png";
break;
case "循环":
trueUrl = "https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1552469926587&di=a3b53aa7c4a4934cc11659d1012cda05&imgtype=0&src=http%3A%2F%2Fpic.51yuansu.com%2Fpic3%2Fcover%2F01%2F64%2F60%2F595710c280190_610.jpg";
clickUrl= "http://img2.imgtn.bdimg.com/it/u=1694287427,1534841493&fm=26&gp=0.jpg";
break;
case "数学":
trueUrl = "https://ss0.bdstatic.com/70cFuHSh_Q1YnxGkpoWK1HF6hhy/it/u=4064586137,4089318435&fm=26&gp=0.jpg";
clickUrl= "http://img2.imgtn.bdimg.com/it/u=1694287427,1534841493&fm=26&gp=0.jpg";
break;
case "列表":
trueUrl = "https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1552470101548&di=ea43919ba160ac50a6bece8757d4291c&imgtype=0&src=http%3A%2F%2Fpic46.nipic.com%2F20140814%2F19268738_232534528000_2.jpg";
clickUrl= "http://img2.imgtn.bdimg.com/it/u=1694287427,1534841493&fm=26&gp=0.jpg";
break;
default:
trueUrl = "http://img1.imgtn.bdimg.com/it/u=929944757,2734192754&fm=26&gp=0.jpg";
clickUrl= "http://img2.imgtn.bdimg.com/it/u=1694287427,1534841493&fm=26&gp=0.jpg";
break;
}
}
return {
clickUrl:clickUrl,
trueUrl:trueUrl
};
}
其中注意到 this.html_.privateDoNotAccessOrElseSafeHtmlWrappedValue_ 是干嘛的呢,这个是获取类别内容的也就是那些个case
那么你该问了,具体是在哪生成左侧tree的呢,好把我们的代码放到相应的位置
so:
// 获取行内html样式
goog.ui.tree.BaseNode.prototype.getRowSafeHtml = function() {
var a = {};
a["padding-" + (this.isRightToLeft() ? "right" : "left")] = this.getPixelIndent_() + "px";
a = { "class": this.getRowClassName(), style: a };
//判断如果不为空 再生成img
var b = [this.getExpandIconSafeHtml(), this.getIconSafeHtml(), this.getLabelSafeHtml(), this.html_.privateDoNotAccessOrElseSafeHtmlWrappedValue_ ? this.getLabelSafeself() : ''];
return goog.html.SafeHtml.create("div", a, b)
};
上面的b数组就是存储将来要遍历生成dom的,我们把生成image的添加进去,不过这里需要注意的是只给类别前添加icon
所以我们只需要给有类别的blocklyTreeRow的div下添加咱们的icon ,还记得我们刚才说的this.html_.privateDoNotAccessOrElseSafeHtmlWrappedValue_ 吗?这个就是类别信息,所以说我们在给b赋值的时候三目了一下,你就应该懂了是什么意思了
样式添加完成之后,有个问题就来了,点击效果怎么加?
提供给你们一个思路吧:
$('body').on('touchstart', '.blocklyTreeRow', function() {
let bj = JSON.parse($(this).children('img').attr('backgroundData'));
redoColor();
$(this).children('img').attr('src', bj.clickUrl);
})
const redoColor = () => {
let obj = $('.blocklyTreeRow');
for (let i = 0; i < obj.length; i++) {
i != 0 && obj.eq(i).children('img').attr('src', JSON.parse($('.blocklyTreeRow').eq(i).children('img').attr('backgroundData')).trueUrl);
}
}
因为我的项目这里需要一个点击换icon,所以说我在创建dom的时候就绑定了其点击后的变换信息,然后js去控制换图,只是一个思路,你也可以直接修改源码实现。
接下来你就可以随意的创建dom来完成自己的交互样式了、
博主菜单栏的块和工作区域的是不一样,所以又修改了菜单生成(左边挂图片就可以了) 效果图如下:
以上代码研究都是我们项目需要,所以说我花了一个多月去看blcokly,所有的改动都是自己的想法,很可能大家有更好的想法,
点个关注呗,项目中还有很多瑕疵在优化,接下来我会接着更新
如何自定义生成代码(博主的项目生成的c++代码)、如何自定义blockly块的形状,以及块与块之间的衔接交互如何修改,
还有就是一个小更改,比如说根据变量的类型,生成不同的变量,这些都会在后续文档中写出来,