html5可视化图形编辑器(基于canvas)

时间:2020-12-04 17:58:58
我以前特别喜欢flash,不过flash水平一般,那是的我并不是程序员,充其量也就是个爱好者,在这个html5的时代中,我依旧对那个有时间轴的flash编辑界面念念不忘。于是便有了这篇文章。我的目标是做一款在线的图片,文档,动画,游戏生成器。目标比较大(个人比较贪),目前只实现了一部分,但是我相信时间能缔造一切,也希望大神们多多帮忙,谢谢了!我把所有的代码写上来,一是帮我记录开发过程,二是供大家查看研究,有兴趣的多多留言交流。

创建一个js文件起好响亮大名在webstorm中不写hello,写一个html5中的flash,一个基于canvas(并非基于SVG)的强大框架(哈哈目标远大,任务重啊!)

面向对象可以简化开发难度,便于维护,为了做到更好的面向对象,要对js中的一些东西进行完善。
1先拿数组开刀







/**
* 删除数组的元素
*/

Array.prototype.remove = function (val) {
    if (val != null && this.length > 0) {
        for (var i = 0; i < this.length; i++) {
            if (this[i] == val) {
                this.splice(i, 1);
                break;
            }
        }
    }
}
/**
 *
 * 删除指定索引处元素
 * @param dx
 * @returns {Array}
 */
Array.prototype.del = function (dx) {
    if (isNaN(dx) || dx > this.length || dx < 0) {
        return this;
    } else {
        this.splice(dx, 1);
    }
}
/**
 *
 * 向数组末尾追加一个元素
 * @param val
 * @returns {Number|number}
 */
Array.prototype.add = function (val) {
    if (val != null) {
        return  this.push(val);

    }
}
/**
 *
 * 清空数组
 * @returns {Array|T[]}
 */
Array.prototype.clear = function () {
    return this.splice(0, this.length);
}

/**
 *
 *
 * 交换两个元素的值
 * @param index1
 * @param index2
 * @returns {*|T}
 */
Array.prototype.swap = function (index1, index2) {
    if (index1 < this.length && index2 < this.length && index1 >= 0 && index2 >= 0) {

        return  this[index1] = this.splice(index2, 1, this[index1])[0];
    }
}
/**
 * 数组上移
 * @param index
 */
Array.prototype.up = function (index) {
    if (index != null && index >= 0 && index < this.length) {
        if (index == 0) {
            return;
        }
        this.swap(index, index - 1);
    }
};
/**
 *
 *
 * 数组下移
 * @param index
 */
Array.prototype.down = function (index) {
    if (index != null && index >= 0 && index < this.length) {
        if (index == this.length - 1) {
            return;
        }
        this.swap(index, index + 1);
    }
};
/**
 *
 * 数组元素变为第一个元素
 * @param index
 */
Array.prototype.dips = function (index) {
    if (index != null && index >= 0 && index < this.length) {
        if (index == 0) {
            return;
        }
        this.swap(index, 0);
    }
}
/**
 *
 *  数组元素变为最后一个元素
 * @param index
 */
Array.prototype.floats = function (index) {
    if (index != null && index >= 0 && index < this.length) {
        if (index == this.length - 1) {
            return;
        }
        this.swap(index, this.length - 1);
    }
}
Array.prototype.find = function (val) {
    if (this.length > 0) {

        for (var i = 0; i < this.length; i++) {
            if (this[i] == val) {

                return i;
            }

        }

    }

}


以上是对数组的改造,这些东西以后会派上大用处,不过有些方法并不完善,有漏洞,需要进一步完善!


2 全局对象

要撰写专业的js框架而言,一般采用这种方式书写,这种方式实现了所谓的私有化变量和方法。比如jquery就是这种写法,对于框架安全有重要意义,对于外部要访问的方法可以在其前面加上window。由于本人是个急性子想要现实现功能后在对框架进行封装(习惯不好哈哈哈!所以就没有使用这种的)

(function(){

//js code



})()




一些全局对象
由于想写一个独立的框架,不想使用jquery(虽然很方便)
获取dom对象
</pre><div></div><div><pre class="javascript" name="code">var scaneArray = new Array();
var layerArray = new Array();

/***
*
* 场景
* @constructor
*/
function Scane() {
scaneArray.add(this);
this.id = '';
this.playtime = 1000; //指定场景播放时间
this.playflag = false;
this.order = ''; //场景编号
this.loopflag = false; //循环标志
this.nextframe = ""; //在限定时间播放后调到指定编号场景
this.layer = new Layer(); //场景中的图层
this.addplayer = function (val) {
this.layer.array.add(val);
}
this.startplay = function () {
this.playflag = true;
}
this.stopplay = function () {
this.playflag = false;
}
}

/**
*
*
* 场景中的层
* @constructor
*/
function Layer() {
this.array = new Array();
this.add = function (val) {
this.array.add(val)

}
this.remove = function (val) {
if (this.array.length > 0) {
//alert(val);
for (var i in this.array) {
if ((val == this.array[i]) && this.array[i].role == "weather") {

$s("stage").removeChild($s(val.id));


}
if ((val == this.array[i]) && this.array[i].role == "pickj") {

$s("stage").removeChild($s(val.canId));


}
}
this.array.remove(val);
}
}

this.top = function (val) {
if (this.array.length > 0) {
this.array.floats(this.array.find(val));

}


}

this.clear=function(){
if (this.array.length > 0) {
for (var i in this.array) {
this.remove(this.array[i]);
}
}
}

this.hides=function(){

if (this.array.length > 0) {

for (var i in this.array) {

if (this.array[i].role === "pickj"&&$s(this.array[i].canId)!=null) {

$s(this.array[i].canId).width=0;
$s(this.array[i].canId).height=0;

}
}
}
}

this.show=function(){
if (this.array.length > 0) {
for (var i in this.array) {
if (this.array[i].role === "pickj"&&($s(this.array[i].canId))!=null) {

$s(this.array[i].canId).width=this.array[i].w;
$s(this.array[i].canId).height=this.array[i].h;


}
}
}
}

}


舞台的实现
function Stage(w, h, color, id,bg) {
Stage.array = array;
Stage.cmdArray = cmdArray;
Stage.shapeArray = shapeArray;
Stage.background=bg;
Stage.w = w;
Stage.h = h;
canvas.width = w;
canvas.height = h;
canvas.style.backgroundColor = color;
onload = function () {

try {

document.getElementById(id).appendChild(canvas);

Toolcan=document.getElementById("timeline");
toolpaint=Toolcan.getContext("2d");


} catch (e) {
alert("找不到对应的id值无法创建画板" + e.message);


}
};
Stage.update = function () {


}
Stage.draw = function () {


}
Stage.Aexe = function (mv) {

if (cmdArray.length > 0) {


if (cmdArray != null && cmdArray.length > 0) {

setInterval(function () {
if (i < cmdArray.length) {
mc.speed = 1;
mc.statu = true;
mc.shortsport = true;


if (cmdArray[i] == 'up') {

mc.fx = 'up'


} else if (cmdArray[i] == 'down') {

mc.fx = 'down'


} else if (cmdArray[i] == 'left') {

mc.fx = 'left'


} else if (cmdArray[i] == 'right') {

mc.fx = 'right'


}
i++;
}
}, 1000);
}
}


}


Stage.findScane=function(id){
if(scaneArray.length>0){

for(var i=0;i<scaneArray.length;i++){
if(scaneArray[i].id==id) {
return scaneArray[i];
}}}
}


Stage.removeScane=function(id){
if(scaneArray.length>0){

for(var i=0;i<scaneArray.length;i++){
if(scaneArray[i].id==id){
scaneArray.remove(scaneArray[i]);

}


}

}

}


Stage.add = function (moveclip) {
if (moveclip != null) {
if (Stage.array.length == 0) {
Stage.array.push(moveclip);
} else if (Stage.array.length > 0) {
var k = 0
for (var m = 0; m < Stage.array.length; m++) {
if (moveclip.id !== Stage.array[m].id) {
k++;


} else {
alert("id=" + id + "id重复,请更换!");
return;
}
}
if (k >= Stage.array.length) {
Stage.array.push(moveclip);

}
}
}
};
Stage.remove = function (val) {
if (val != null) {
Stage.array.remove(val);
}
};
Stage.findByid = function (id) {

if (id != null && Stage.array.length > 0) {

for (var i = 0; i < Stage.array.length; i++) {
if (Stage.array[i].id == id) {
return Stage.array[i];
}

}
} else {
return null;
}
}



Stage.removeById = function (id) {
if (id != null && Stage.array.length > 0) {
var k = 0;
for (var i = 0; i < Stage.array.length; i++) {
if (Stage.array[i].id == id) {


Stage.array.remove(Stage.array[i]);
} else {
k++;
if (k >= Stage.array.length) {


alert("此id不存在!")
}

}

}


}
}





重点说一下如何实现flash中的舞台,时间轴,层的 场景的概念

我把flash中的帧的概念当作一个场景(scane),一副画面。场景中的画面又有了层(Layer)的概念。
今天就说到这里。明天继续!