HT for Web基于HTML5的图像操作(一)

HT for Web独创的矢量图片设计架构,使其具有强大丰富的动态图形呈现能力,但从最近知乎热议的“Adobe Photoshop 是否已经过时?”的话题,大家能体会到很多情况下实际项目不可能完全采用矢量,项目中还是有大量的传统非矢量的静态图片,毕竟工具强大且现有资源丰富,但为了使静态图片呈现出更多的动态效果,HT for Web提供了较多渲染方式,例如对HT for Web的图元设置‘body.color’的style后图元即可达到自动染色的效果,这里将对这种染色技术进行讲解。

上图呈现了本文例子最终的呈现效果,中间为原始图片是http://hightopo.com/images/banner.png ,对其分别设置了红、黄和蓝三种颜色后的染色效果,完全基于HT for Web实现这么个简单拓扑的话代码不过十多行,不过今天我们不借助HT for Web提供的‘body.color’的染色功能,我们将采用最原始的方式生产染色图片。

dataModel = new ht.DataModel();                   
	graphView = new ht.graph.GraphView(dataModel); 
	graphView.addToDOM();
	var root = new ht.Node();
	root.setImage('ht-for-web.png');
	dataModel.add(root);                                
	['blue', 'yellow', 'red'].forEach(function(color){
		var node = new ht.Node();
		node.setImage('ht-for-web.png');
		node.s({ 'body.color': color });
		dataModel.add(node);             
		var edge = new ht.Edge(root, node);
		edge.s({'edge.color': color});
		dataModel.add(edge);                    
	});

染色的原理就是对图片像素内容的操作,可以理解为一个 convertColor(r, c, rawColor, …)->finalColor 的像素函数转换, 其中的r和c分别代表像素所在行和列,rawColor为原始颜色信息,…代表其他的参数信息,例如我们进行染血的颜色信息,最终通过convertColor处理返回的finalColor为转换后的像素值。

图片染色操作可以说是最简单的图像处理了,本质就是rawColor * tintColor,这里的tintColor可以理解为HT for Web的body.color值,一般该信息代表监控系统的告警级别状态等信息,通过染色让用户更直观的观察到设备运行告警状态。这里的rawColor * tintColor相乘是本质是分别对两个颜色的rgb进行相乘,一般情况下最后的alpha的透明度,会保持原始rawColor的值不进行操作处理。

toRGBA = (function(){
		var map = {}, // string - [128,128,128,255]
			canvas;
		return function(color){
			var g, data = map[color];
			if (!data) {
				if(!canvas){
					canvas = document.createElement('canvas'); 
					canvas.width = 1;
					canvas.height = 1;
				}
				g = canvas.getContext('2d');
				g.clearRect(0, 0, 1, 1);          
				g.fillStyle = color;
				g.beginPath();
				g.rect(0, 0, 1, 1);
				g.fill();                                                
				data = g.getImageData(0, 0, 1, 1).data;
				data = map[color] = [data[0], data[1], data[2], data[3]];
			}
			return data;           
		};
	})();            

	function init(){    
		var image = new Image();
		image.src = 'banner.png';// 'ht-for-web.png';
		image.onload = function(){
			dataModel = new ht.DataModel();                   
			graphView = new ht.graph.GraphView(dataModel); 
			graphView.addToDOM();

			var root = new ht.Node();
			root.setImage(image);
			dataModel.add(root);  

			['blue', 'yellow', 'red'].forEach(function(color){
				var node = new ht.Node();
				node.setImage(createColorImage1(image, color));                        
				dataModel.add(node);             
				var edge = new ht.Edge(root, node);
				edge.s({
					'edge.color': color
				});
				dataModel.add(edge);                    
			});                     
		};
	}
	function createColorImage1(image, color) {
		var width = image.width;
		var height = image.height;                
		var canvas = document.createElement('canvas');
		var context = canvas.getContext( "2d" );
		canvas.width = width;
		canvas.height = height;
		context.drawImage(image, 0, 0, width, height);                
		var rgba = toRGBA(color);
		var r = rgba[0]/255, g = rgba[1]/255, b = rgba[2]/255;
		var pixelData = context.getImageData(0, 0, width, height);
		var pixels = pixelData.data;
		for (var i = 0; i < pixels.length; i += 4)
		{
			pixels[i+0] *= r;
			pixels[i+1] *= g;
			pixels[i+2] *= b;
		}
		context.putImageData(pixelData, 0, 0);
		return canvas;
	}

以上代码为实现的全部逻辑,有两点需要注意,颜色值通过getImageData返回的是0~255的值,进行染色相乘我们需要基于0~1的格式,因此需要先除以255转换后再相乘。另外一点为了方便用户开发,颜色值允许是任意html支持的颜色格式,有可能输入red,rgba(255,125,128,0.1)等格式,以上toRGBA代码在闭包中返回了个可根据输入格式返回颜色数组的工具函数,其借助的也是在一个像素的canvas内存中动态绘制,再通过getImageData来决定颜色信息,再通过map缓存计算结果,这种方式比枚举一堆颜色映射表来得精简。

当然采用这种染色算法在图元是纯黑色的时候是有问题的,因为黑色的rgb值都为0,因此无论乘以什么颜色结果也都为0,实际应用场景可以要求美工避免做纯黑色的图片,或者代码对纯黑色的图片进行特殊的运算处理。

以上方式仅是第一种染色方式,因此为createColorImage1,下篇将介绍第二种染色方式createColorImage2。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Coco的专栏

【CSS进阶】原生JS getComputedStyle等方法解析

24650
来自专栏HTML5学堂

2016.06 第一周 群问题分享

HTML+CSS meta标签的viewport属性说明 2016.05.30~2016.06.03 核心概念 viewport(视口) 参考答案 <meta ...

30370
来自专栏我的博客

Jquery学习第一天

1、jQuery优点 轻量级,强大的选择器,出色的DOM操作,可靠的事件处理,完善的Ajax,不污染的顶级变量,出色的浏览器兼容,链式操作,隐式迭代,行为层和结...

37780
来自专栏阿凯的Excel

自定义单元格格式介绍(第二期 文本版)

上期和大家分享了自定义条件格式的数字版。本期继续和大家分享文本的自定义单元格格式! 继续强调啰嗦两件事情!!! 1、自定义单元格格式只改变显示内容,不改变实...

29860
来自专栏偏前端工程师的驿站

CSS魔法堂:"那不是bug,是你不懂我!" by inline-block

前言  每当来个需要既要水平排版又要设置固定高宽时,我就会想起display:inline-block,还有为了支持IE5.5/6/7的hack*display...

22180
来自专栏前端儿

编写高质量 JavaScript -- 知识点小记

此番改善之后,匿名function里面的变量作用域不再是window,而是局限在函数内。

20510
来自专栏deepcc

css3 box-sizing属性

36560
来自专栏柠檬先生

jQuery 效果使用

.hide()   隐藏匹配的元素。   .hide()     这个方法不接受任何参数。   .hide([duration][,comp...

21590
来自专栏码神联盟

碎片化 | 第四阶段-41-struts2字节流生成验证码-视频

如清晰度低,可转PC网页观看高清版本: http://v.qq.com/x/page/r056700jckx.html 验证码实现 需求: 在登录的页面,增...

30090
来自专栏哲学驱动设计

OEA 中 WPF 树型表格虚拟化设计方案

    最近用 OEA 做的仓库管理系统中,许多界面的都需要使用表格控件来显示数据。一是这些表格的列非常多,有的甚至达到了 200 列,而且一个模块的界面中可能...

21670

扫码关注云+社区

领取腾讯云代金券