当前位置: 首页 > 编程日记 > 正文

利用box-shadow绘图

上篇博客提到过,box-shadow属性的本质是对形状的复制,那么如果我设置一个1*1px的i标签,利用box-shadow可以叠加的特性,给每一个1*1px的阴影赋上颜色,那么最后不就是一幅图片了么。

html代码很简单:

<!doctype html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
<title>canvas</title>
<style>#shadow {position: relative;}#shadow i {display: block;width: 1px;height: 1px;}
</style>
<script src="shadowShow.class.js" defer="defer"></script>
</head>
<body>
<input id="file" class="file-upload" type="file" accept="image/png, image/gif" />
<canvas id="canvas">您的浏览器不支持canvas标签
</canvas>
<div id="shadow"><i></i></div>
<script>
var init = {fileObj: 'file',  //input控件的idcanvas: 'canvas',  //canvas的标签的idshadowBox: 'shadow',  //用于阴影显示的标签的id
};
</script></body>
</html>

做了一个简单的图片上传控件,页面的js里读取了一些简单的控件信息。

最初在直接用控件获取图片路径时,碰到了路径显示为fakepath的问题(直接给控件赋路径src='#'有效果),所以没法读取图片的路径。

查询后使用了FileReader()解决了这个问题,FileReader()读取图片信息的使用很简单,请自行百度。

重点还是用canvas的getImageData()获取了图片每个像素点的rgba信息。图片上的每个点都有rgb三原色加上一个透明度的信息,这些信息都放在getImageData()的data数组里,换句话说,data数组里每4个值组合起来就是一个像素点的颜色信息。而每个像素点的位置可以根据这是第几个像素点(每个像素点都是1*1px),加上原图片的长宽信息来计算得出,宽度上data数组里每4个值宽度加1px,如果像素点的宽度超过了图片的宽度,那么就说明该像素点是下一行的,即将高度加1px,宽度重置。

又像素点的信息都是保存在一个名叫data的一维数据里,且每4条数据是一个像素点的颜色信息,所以可以每4条数据一读,比如 if (i % 4 === 0),那么像素点的red通道即是image.data[index],green通道是imageData.data[index + 1],blue通道是imageData.data[index + 2],alpha通道是imageData.data[index + 3],最后把这些颜色信息处理下通通push到一个数组里,赋给i标签的box-shadow属性就大功告成。

下面给出完整的js代码:

(function() {/**最初我的init方法是这样的,但是在对象的属性里添加监听事件貌似无效,所以挪到了对象外init: function() {console.log(this.fileObj);this.fileObj.addEventListener('change', function() {shadowShow.upPic();});},*/document.getElementById(init.fileObj).addEventListener('change', function() {shadowShow.init();});var shadowShow =  {fileObj: document.getElementById(init.fileObj),canvas: document.getElementById(init.canvas),ctx: this.canvas.getContext('2d'),shadowBox: document.getElementById(init.shadowBox),init: function() {shadowShow.upPic();},/***用于获取上传的图片的信息并在canvas1中显示*@method upPic*/upPic: function() {image = new Image();this.setImageUrl(image, this.fileObj);image.onload = function() {// cavas的宽高用setAttribute设置,用canvas.width也可以,注意值不能加上单位width = this.width;height = this.height;shadowShow.canvas.setAttribute('width', width);shadowShow.canvas.setAttribute('height', height);shadowShow.ctx.drawImage(this, 0, 0, width, height);shadowShow.toShadowShow(this, shadowShow.ctx);}},/***用于设置创建的iamge对象的url*@method setImageUrl*@param {obj} image 创建的iamge对象*@param {obj} fileQuery 上传图片的file控件对象*/setImageUrl: function(image, fileQuery) { var file = fileQuery.files[0]; var reader = new FileReader();  reader.onload = function(e) { image.src = e.target.result;}reader.readAsDataURL(file);  },/***用于将上传的图片的用box-shadow表现出来*@method toBoxShadow*@param {obj} image 创建的iamge对象*@param {obj} context 创建的绘图的上下文对象*/toShadowShow: function(image, context) {width = image.width;height = image.height;this.shadowBox.style.width = width + 'px';this.shadowBox.style.height = height + 'px'; var imageData = context.getImageData(0, 0, width, height);var arrShadow = new Array();var index = 0;var interval = setInterval(function() {if (index < imageData.data.length) {// 每4个参数处理一次if (index % 4 === 0) {var x = index / 4 % width + 1,  //x坐标,以index=4为例,index/4=1,表示x是第1个像素点,1%width是为了获得第n行的像素点的x坐标,又index是从0开始的(index=0是真正的第一个像素点),所以x的坐标需要加上1y = Math.floor(index / 4 / width) + 1, //y坐标,alpha = Math.round(imageData.data[index + 3] / 255 * 100) / 100;  //透明度,imageData.data[index+3]/255需要乘以100是因为(imageData.data[index+3]/255)肯定是小于1的,为了避免round()取整值为1,故需要乘以100if (alpha == 255) {  //像素点没有透明度//将rgb转为16进制var redToHex = imageData.data[index].toString(16),greenToHex = imageData.data[index + 1].toString(16),blueToHex = imageData.data[index + 2].toString(16);redToHex = redToHex.length == 1 ? ('0' + redToHex) : redToHex;greenToHex = greenToHex.length == 1 ? ('0' + greenToHex) : greenToHex;blueToHex = blueToHex.length == 1 ? ('0' + blueToHex) : blueToHex;var hex = redToHex + greenToHex + blueToHex;//对形如#FFF的十六进制颜色作处理if (redToHex.slice(0,1) == redToHex.slice(-1) && greenToHex.slice(0,1) == greenToHex(-1) && blueToHex.slice(0,1) == blueToHex.slice(-1)) {hex = redToHex.slice(-1) + greenToHex.slice(-1) + blueToHex.slice(-1);}arrShadow.push(x + 'px ' + y + 'px #' + hex);} else if (alpha > 0) {a = [imageData.data[index], imageData.data[index + 1], imageData.data[index + 2], alpha].join();arrShadow.push(x + 'px ' + y + 'px rgba(' + a + ')');} }shadowShow.shadowBox.querySelector('i').style.boxShadow = arrShadow.join(); } else {clearInterval(interval);  //清除setInterval}index++;});    }};
})();

这段代码我封装了一下,注释写的比较详细了,同时,加了一个定时器,这样就有了一个像素一个像素显示的效果,就是如果图片的width和height值比较大的话,完整的图片显示出来会比较慢。setInterval()的默认值查了下,如果设置的时间间隔小于10,则以10来算,即10ms,但是还是感觉图片显示的挺慢的,当然了,这要看图片的像素点的数量了。

补充:

当然了,如果仅需遍历每个像素点其实也不用像上面那么麻烦(上面主要是为了获得每个点的坐标(x, y)),如下就可以了:

//简单的灰阶过滤器
for (i = 0; i < imageData.data.length; i += 4) {var r = data[i],g = data[i + 1],b = data[i + 2],a = data[i + 3];var average = Math.floor((r + g + b) / 3);data[i] = data[i + 1] = data[i + 2] = average;
}

最后更新于2016年11月22日

转载于:https://www.cnblogs.com/youyouluo/p/5839709.html

相关文章:

为什么要使用Go语言?Go语言的优势在哪里?

链客&#xff0c;专为开发者而生&#xff0c;有问必答&#xff01; 此文章来自区块链技术社区&#xff0c;未经允许拒绝转载。 Go语言之所有越来越受到开发者的欢迎&#xff0c;我认为与其超高的实用价值密不可分。要知道Go语言是为了解决现实问题而设计的&#xff0c;而不是为…

BI之SSAS完整实战教程3 -- 创建第一个多维数据集

上一篇我们已经完成了数据源的准备工作&#xff0c;现在我们就开始动手&#xff0c;创建第一个多维数据集(Cube)。 文章提纲 使用多维数据集向导创建多维数据集 总结Cube设计器简介 维度细化 总结 一、使用向导创建多维数据集 在Analysis Services中&#xff0c;可以通过3种…

python opencv local_threshold_Python-OpenCV中的cv2.threshold

主要记录Python-OpenCV中的cv2,threshold()方法&#xff1b;官方文档 cv2.threshold() def threshold(src, thresh, maxval, type, dstNone): """ 设置固定级别的阈值应用于多通道矩阵 例如&#xff0c;将灰度图像变换二值图像&#xff0c;或去除指定级别的噪声…

java中decimalFormat格式化数值

介绍 我们经常要对数字进行格式化&#xff0c;比如取小数点后两位小数&#xff0c;或者加个百分比符号等&#xff0c;Java提供了DecimalFormat这个类0 和 # 的区别 "#"可以理解为在正常的数字显示中&#xff0c;如果前缀与后缀出现不必要的多余的0&#xff0c;则将其…

GO语言有哪些优势?怎样入门?

链客&#xff0c;专为开发者而生&#xff0c;有问必答&#xff01; 此文章来自区块链技术社区&#xff0c;未经允许拒绝转载。 1、学习曲线 它包含了类C语法、GC内置和工程工具。这一点非常重要&#xff0c;因为Go语言容易学习&#xff0c;所以一个普通的大学生花一个星期就能…

POJ-2955 Brackets

题目大意&#xff1a; 给你一个只由(、)、[、]组成的字符串&#xff0c;问你这个字符串的子串能够匹配的最长长度是多少。 能够匹配的意思是这样的&#xff1a; 1.如果s是个空串&#xff0c;那么它是匹配的。 2.如果子串是(s)或者[s]&#xff0c;那么它也是匹配的&#xff0c;其…

CentOS7.4-btrfs管理及使用

btrfs, B-tree File System, GPL开源文件系统, 支持CoW即读时写入. 核心特性: 多物理卷支持;btrfs可由多个底层磁盘组成支持RAID mkfs.btrfs 命令的man文档支持: raid0, raid1, raid5, raid6,raid10, single or dup联机"添加, 移除, 修改" CoW写时复制更新机制 对文件…

取消对 null 指针“l”的引用。_C++中的引用

当变量声明为引用时&#xff0c;它将成为现有变量的替代名称。通过在声明中添加“&#xff06;”&#xff0c;可以将变量声明为引用。#include using namespace std; int main() { int x 10; // ref is a reference to x. int& ref x; // Value of x is no…

你没听说过的Go语言惊人优点

链客&#xff0c;专为开发者而生&#xff0c;有问必答&#xff01; 此文章来自区块链技术社区&#xff0c;未经允许拒绝转载。 在这篇文章中&#xff0c;我将讨论为什么你需要尝试一下 Go 语言&#xff0c;以及应该从哪里学起。 Go 语言是可能是最近几年里你经常听人说起的编…

JS document

<!DOCTYPE html> <html><head><meta charset"UTF-8"><title></title></head><body><div id"one">今天下雨</div><table border"1" cellspacing"0" cellpadding"…

python 流写入文件_python文件流操作

博主在学习python时对文件进行操作时经常踩一下坑。所以专门梳理了一下。有问题麻烦指出哈。 python对于文件的操作我们一般是用open&#xff08;&#xff09;。我们根据python的源码可以看出。我们必须要传的参是file即打开文件的URL。同时open方法默认是是r的打开方式即只读。…

使用 Python 从零开始开发区块链应用程序

链客&#xff0c;专为开发者而生&#xff0c;有问必答&#xff01; 此文章来自区块链技术社区&#xff0c;未经允许拒绝转载。 “区块链”是什么&#xff1f; 区块链是一种存储数字数据的方式。数据可以是任何内容。对于比特币&#xff0c;它是事务&#xff08;在帐户之间转移…

Mybatis学习记录-使用问题总结之一DISTINCT

问题1&#xff1a;手动修改的查询语句&#xff0c;放入到项目中后显示结果和实际查询结果不一致 由于实际情况中用的了分页功能&#xff0c;导致最终的语句在查询完成后&#xff0c;添加了分页项&#xff0c;即如下代码。 ROW_NUMBER() OVER ( ORDER BY COLUMNS) PAGE_ROW_NUMB…

python xlrd读取excel所有数据_python读取excel进行遍历/xlrd模块操作

我就废话不多说了&#xff0c;大家还是直接看代码吧~ #!/usr/bin/env python # -*- coding: utf-8 -*- import csv import xlrd import xlwt def handler_excel(filenamer/Users/zongyang.yu/horizon/ops_platform/assets/upload/1.xlsl): # 打开文件 workbook xlrd.open_work…

【NOIP2015提高组Day1】 神奇的幻方

【问题描述】 幻方是一种很神奇的 N*N矩阵&#xff1a;它由数字1,2,3, … … ,N*N 构成&#xff0c;且每行、每列及两条对角线上的数字之和都相同。 当N为奇数时&#xff0c;我们可以通过以下方法构建一个幻方&#xff1a; 首先将1写在第一行的中间。 之后&#xff0c;按如下…

40行python开发一个区块链

链客&#xff0c;专为开发者而生&#xff0c;有问必答&#xff01; 此文章来自区块链技术社区&#xff0c;未经允许拒绝转载。 尽管有人认为区块链目前还是个不成熟的解决方案&#xff0c;但它无疑称得上是计算机发展历史上的一个奇迹。但是&#xff0c;到底区块链是什么呢?…

网络实验的背景流

在最近做的网络实验中&#xff0c;发现背景流必须要先于实验流开始&#xff0c;并且要长于实验流的时间&#xff0c;这样才能看出实验流的规律。如果背景流后发于实验流&#xff0c;就会变成竞争模式&#xff0c;实验流就会被抢占或者挤压。转载于:https://www.cnblogs.com/fen…

python捕获异常后处理_python异常捕获处理

一、异常处理 在程序运行过程中&#xff0c;总会遇到各种各样的错误。程序一旦出错就停止运行了&#xff0c;此时就需要捕捉异常&#xff0c;通过捕捉到的异常&#xff0c;我们再去做对应的处理 写一个函数&#xff0c;实现除法运算 def calc(a,b): return a/b print(calc(5,1)…

《JS权威指南学习总结--第十一章子集和扩展》

js子集和扩展&#xff1a;http://www.cnblogs.com/ahthw/p/4298449.html ES6新增let和const关键字&#xff1a;http://www.cnblogs.com/telnetzhang/p/5639949.html JS中 var 和 let 关键字的区别&#xff1a;http://www.w3cfuns.com/notes/21400/891cac0f6bff2d7f25d3084618e8…

最常见的 35 个 Python 面试题及答案

链客&#xff0c;专为开发者而生&#xff0c;有问必答&#xff01; 此文章来自区块链技术社区&#xff0c;未经允许拒绝转载。 作为一个 Python 新手&#xff0c;你必须熟悉基础知识。在本文中我们将讨论一些 Python 面试的基础问题和高级问题以及答案&#xff0c;以帮助你完…

PHP 中日期时间函数 date() 用法总结

[导读] date()是我们常用的一个日期时间函数&#xff0c;下面我来总结一下关于date()函数的各种形式的用法&#xff0c;有需要学习的朋友可参考。格式化日期date() 函数的第一个参数规定了如何格式化日期 时间。它使用字母来表示日期和时间 格式化日期date() 函数的第一个参数规…

mac mysql的安装

mac是重装的系统&#xff0c;很干净&#xff0c;没有xmpp等组合的服务器。 1. 安装mysql server https://dev.mysql.com/downloads/mysql/ 这里是官网地址&#xff0c;选择需要的版本下载&#xff0c;我下载的是第一个dmg的&#xff0c;进入后&#xff0c;会让登陆或注册&#…

windows系统和linux系统可以使用相同的js代码吗_「React 手册 」在 Windows 下使用 React , 你需要注意这些问题...

大家好&#xff0c;本篇内容&#xff0c;我要和大家聊聊使用 Windows 开发 React &#xff0c;你需要注意的一些问题。首先说明下&#xff0c;我不是使用 windows 进行开发&#xff0c;因为其配置开发环境来说不是特别方便&#xff0c;我更喜欢 苹果mac 或者乌班图这样的系统&a…

以太坊:比特币 + 无限可能

链客&#xff0c;专为开发者而生&#xff0c;有问必答&#xff01; 此文章来自区块链技术社区&#xff0c;未经允许拒绝转载。 还记你得刚学编程时&#xff0c;第一次使用“对象”的感觉吗&#xff1f;还记你第一次尝试函数式编程的样子吗&#xff1f;这些编程范式&#xff0…

thinkphp5内置标签

thinkphp5内置标签 知道内置标签怎么用&#xff0c;查手册的时候好查 却功能的时候在里面找着来用 内置标签一览 1 内置标签2 3 变量输出使用普通标签就足够了&#xff0c;但是要完成其他的控制、循环和判断功能&#xff0c;就需要借助模板引擎的标签库4 功能了&#xff0c;系统…

python可视化窗口制作一个摇骰子游戏_使用python制作一个抽奖小游戏——骰子游戏...

1.模拟真实环境掷骰子 从Python标准库中调用模块&#xff1a;random——random中包含以各种方式生成随机数的函数 从random中引用randint这一函数——骰子都是有固定面数 from random import randint **2. **创建Die类**** 骰子属性sides&#xff08;面数&#xff09;默认为6面…

C#拾遗(一、基本类型)

1. C#是一种块结构语言&#xff0c;用花括号{}分块&#xff0c;但是用#region和#endregion来定义可以展开和折叠的代码区域 #region 这是引用区 using System; ...... #endregion 2. C#简单类型都是小写&#xff0c;bool,string类型要区别于Java的写法&#xff1b;float、decim…

我不喜欢Go语言的十个理由

链客&#xff0c;专为开发者而生&#xff0c;有问必答&#xff01; 此文章来自区块链技术社区&#xff0c;未经允许拒绝转载。 Go 语言有多火爆&#xff1f;国外如 Google、AWS、Cloudflare、CoreOS 等&#xff0c;国内如七牛、阿里、知乎等都已经开始大规模使用 Go 语言开发…

写扩展性好的代码:函数

http://blog.jobbole.com/107442/转载于:https://www.cnblogs.com/answercard/p/8862006.html

PHP学习笔记:万能随机字符串生成函数(已经封装好)

做验证码用到的&#xff0c;然后就把这个函数封装起来&#xff0c;使用时候要设置2个参数&#xff1a; $str设置里要被采集的字符串&#xff0c;比如&#xff1a; $strefasfgzsrhftjxjxjhsrth; 则在函数里面生成的字符串就回从efasfgzsrhftjxjxjhsrth里面随机抓取&#xff1b; …