作为一名前端的初学者,此篇文章作者只保证原创以及在一般条件下可用。

  这是在某个特殊需求中,我个人写的一个异形按钮组件,可以作为初学者学习的参考,主要使用了canvas、js等技术。可以在html页面中创建一个支持像素级操作的异形按钮(需要图片格式支持是为了作为判断是否点击/移动到了图片之上,作为依据。注:png格式/svg格式等才拥有无色区域,无色!=白色!!!;

  另外支持使用背景图片或者直接设置宽高的方式处理canvas对象,也可以不设置 由css/html结构中书写。

  注:常识性问题:canvas对象的width/height!=style.width/style.height!这个 问题适用于大多数html元素。

  由于本插件使用了多个辅助方法。可能会与页面已有方法冲突,如确实有冲突,请更名即可  。

  本插件使用类的方式调用,因此支持同页面多个元素同时使用本插件。

  注! 某些特殊css样式可能导致获取位置失效。可以参考思路,自己书写异形按钮解决方案。

  将下面整体复制后,引入页面即可(推荐使用新的文件,作为引用。)

  如果好用请支持js新人,谢谢。欢迎各路大神大仙大哥大姐交流学习。

function getOffsetTop(obj){
    var tmp = obj.offsetTop;
    var val = obj.offsetParent;
    while(val != null){
        tmp += val.offsetTop;
        val = val.offsetParent;
    }
    return tmp;
}
function getOffsetLeft(obj){
    var tmp = obj.offsetLeft;
    var val = obj.offsetParent;
    while(val != null){
        tmp += val.offsetLeft;
        val = val.offsetParent;
    }
    return tmp;
}
function mousePos(e){ 
  var x,y; 
  return { 
    x:e.clientX+document.body.scrollLeft + document.documentElement.scrollLeft, 
    y:e.clientY+document.body.scrollTop + document.documentElement.scrollTop 
  }; 
}; 
function isin(obj,x,y){
	//解析button有没有被点击到(精确到像素)
	var xmax = obj['xy'][0] + obj.width;
	var ox = x-obj['xy'][0];
	var oy = y-obj['xy'][1];
	if(ox>=0&&ox<obj.width){
		if(oy>=0&&oy<obj.height){
			var canvas = document.createElement('canvas');
			var context = canvas.getContext('2d');
			canvas.width = obj.width;
			canvas.height = obj.height;
			context.drawImage(obj, 0, 0, obj.width, obj.height);
			var colors =  context.getImageData(ox, oy, 1, 1).data;
			if(colors[0]!=0&&colors[1]!=0&&colors[2]!=0&&colors[3]!=0){
				return true;
			}
		}
	}
	return false;
}
function draw(c,b){
	c.clearRect(0,0,c['canvas'].width,c['canvas'].height);
	for(var i = 0;i<b.length;i++){
		if(b[i].isactive||b[i].ishidden){
			c.drawImage(b[i],b[i].xy[0],b[i].xy[1]);
		}
	}
}
function buttabs(can,func,funh){//canvas对象,点击回调函数 , 按钮移动到回调函数
	//调用方法 : 1创建本对象 new  buttabs ();
	//初始化背景图片或者直接设置宽高 (如有需要  可以灵活设置。可以有设置背景图之后有回调函数)
	//addbuts(传入的参数示例)[['img.src',x,y,'返回值'],['img.src',x,y,'返回值2']];
	//buts的返回值将用于在触发任何回调函数时 返回  (用以区别具体点击了那个button)
	//removebuts 清除所有button
	this.func = func;//按钮点击回调函数
	this.funh = funh;//按钮hover回调函数
	this.c = can.getContext('2d');
	this.buts = new Array();
	this.func = null;//按钮点击回调函数
	this.funh = null;//按钮hover回调函数
	this.removebuts(){
		this.buts = new Array();
	}
	this.setback = function(src,fun){
		//设置背景图片会根据背景图片自动设置宽高
		this.backimg = new Image();
		this.backimg.src = src;
		var c = this.c;
		var buts = this.buts;
		this.backimg.onload = function(){
			c['canvas'].width = this.width;
			c['canvas'].height = this.height;
			c['canvas'].style.background = 'url('+this.src+') no-repeat 0 0';
			c['canvas'].style.backgroundSize = '100% 100%';
			draw(c,buts);
			if(fun){
				fun();
			}
		};
	}
	this.setwh = function(w,h){
		this.c['canvas'].width = w;
		this.c['canvas'].height = h;
	}
	this.addbuts = function(data,s){
		var buts = this.buts;
		var func = this.func;
		var funh = this.funh;
		for(var i in data){
			var imgt = new Image();
			imgt.src = data[i][0];	
			imgt.xy = [data[i][1],data[i][2]];
			imgt.ishidden = false;
			imgt.isactive = i==s;
			imgt.titles = data[i][3];
			imgt.onload = imgtok(this.buts,imgt,this.c);
			function imgtok(but,img,c){
				but.push(img);
				draw(c,but);
			}
		}
		this.c['canvas'].onmouseout = function(){
			for(var i=0;i<buts.length;i++){
				buts[i].ishidden = false;
			}
			draw(this.getContext('2d'),buts);
		}
		this.c['canvas'].onclick = function(event){
			isclick(event,this);
		};
		this.c['canvas'].onmousemove = function(event){
			ismousemove(event,this);
		}
		function ismousemove(e,t){
			e = e|| arguments.callee.caller.arguments[0] || window.event ;
			var objTop = getOffsetTop(t);//对象x位置
			var objLeft = getOffsetLeft(t);//对象y位置
			var mouseX = ( e.clientX || e.pageX)+document.body.scrollLeft;//鼠标x位置
			var mouseY = ( e.clientY || e.pageY)+document.body.scrollTop;//鼠标y位置
			//计算点击的相对位置
			var xy = mousePos(e);
			var objX = (xy['x']-objLeft)*(t.width/t.offsetWidth);
			var objY = (xy['y']-objTop)*(t.height/t.offsetHeight);
			//for in
			//buts
			var c = t.getContext('2d');
			var i =0;
			for(;i<buts.length;i++){
				if(isin(buts[i],objX,objY)){
					buts[i].ishidden = true;
					if(funh!=null&&typeof funh=='function'){
						funh(buts[i].titles);
					}
					break ;
				}else{
					buts[i].ishidden = false;
				}
			}
			i++;
			for(;i<buts.length;i++){
				buts[i].ishidden = false;
			}
			draw(c,buts);
		}
		function isclick(e,t){
			e = e|| arguments.callee.caller.arguments[0] || window.event ;
			var objTop = getOffsetTop(t);//对象x位置
			var objLeft = getOffsetLeft(t);//对象y位置
			var mouseX =( e.clientX || e.pageX)+document.body.scrollLeft;//鼠标x位置
			var mouseY =( e.clientY || e.pageY)+document.body.scrollTop;//鼠标y位置
			//计算点击的相对位置
			var xy = mousePos(e);
			var objX = (xy['x']-objLeft)*(t.width/t.offsetWidth);
			var objY = (xy['y']-objTop)*(t.height/t.offsetHeight);
			var c = t.getContext('2d');
			var i =0;
			var tindex = null;
			for(;i<buts.length;i++){
				if(isin(buts[i],objX,objY)){
					buts[i].isactive = true;
					if(func!=null&&typeof func=='function'){
						func(buts[i].titles);
					}
					if(tindex!=null){
						buts[tindex].isactive = false;
					}
					break ;
				}else if(buts[i].isactive){
					tindex = i;
				}
			}
			i++;
			for(;i<buts.length;i++){
				buts[i].isactive = false;
			}
			draw(c,buts);
		}
	}
}