
前端编程之页面放大镜功能的实现
淘过宝的都知道,有些网站需要对商品进行放大镜功能,也就是当鼠标移动到商品上面时,会在旁边出现细节的放大效果,这对于一些商城类网站来说,是一定需要具备的,那么页面放大镜功能是如何来实现的呢?下面就跟大家分享一下。
实现代码:
<style>
html,body{
margin: 0;
padding: 0;
}
.main{
width: 1200px;
margin: 100px auto 0;
display: flex;
}
.box{
width: 400px;
height: 500px;
position: relative;
border: 1px solid red;
display: flex;
flex-flow: column;
justify-content: space-between;
padding: 5px;
}
.box_top{
width: 400px;
height: 400px;
display: flex;
position: relative;
border: 1px solid green;
}
.box_top_left{
width: 400px;
height: 400px;
position: relative;
}
.box_top_left_999{
width: 100%;
height: 100%;
position: absolute;
z-index: 999;
}
.box_top_left_99{
width: 200px;
height: 200px;
position: absolute;
z-index: 99;
background-color: rgb(81, 223, 255);
opacity: 0.5;
display: none;
}
.box_top_left img{
width: 100%;
height: 100%;
}
.box_top_right{
width: 400px;
height: 400px;
overflow: hidden;
position: absolute;
left: 500px;
border: 1px solid red;
display: none;
}
.box_top_right img{
width: 800px;
height: 800px;
position: relative;
display: block;
}
.box_bottom{
width: 400px;
height: 80px;
display: flex;
align-items: center;
border: 1px solid blue;
padding: 1% 0;
}
.box_bottom img{
width: 23%;
height: 100%;
margin: 0 1%;
}
</style>
</head>
<body>
<main>
<div class="main">
<div class="box">
<div class="box_top">
<div class="box_top_left">
<div class="box_top_left_999"></div>
<div class="box_top_left_99"></div>
<img src="imgs/timg.jpg" alt="">
</div>
<div class="box_top_right">
<img src="imgs/timg.jpg" alt="">
</div>
</div>
<div class="box_bottom">
<img src="imgs/timg.jpg" alt="">
<img src="imgs/b.jpg" alt="">
<img src="imgs/c.jpg" alt="">
<img src="imgs/d.jpg" alt="">
</div>
</div>
</div>
</main>
<script>
$(".box_bottom img").each(function(){
$(this).mouseover(function(){
$(".box_top_left img").attr("src",$(this).attr("src"))
$(".box_top_right img").attr("src",$(this).attr("src"))
})
})
$(".box_top_left_999").mousemove(function(e){
var top = e.pageY;
var left = e.pageX;
$(".box_top_left_99").css("display","block")
$(".box_top_right").css("display","block")
var new_left_x = $(this).offset().left+100;
var new_left_d = $(this).offset().left+300;
var img_left = left - new_left_x
img_left = -img_left
img_left = img_left*2
if( left > new_left_x){
if(left < new_left_d){
$(".box_top_left_99").css("left",left - new_left_x)
$(".box_top_right img").css("left",img_left)
}else{
$(".box_top_left_99").css("left",200)
$(".box_top_right img").css("left",-400)
}
}else{
$(".box_top_left_99").css("left",0)
$(".box_top_right img").css("left",0)
}
var new_top_x = $(this).offset().top+100;
var new_top_d = $(this).offset().top+300;
var img_top = top - new_top_x
img_top = -img_top
img_top = img_top*2
if(new_top_x < top){
if(new_top_d>top){
$(".box_top_left_99").css("top",top - new_top_x)
$(".box_top_right img").css("top",img_top)
}else{
$(".box_top_left_99").css("top",200)
$(".box_top_right img").css("top",-400)
}
}else{
$(".box_top_left_99").css("top",0)
$(".box_top_right img").css("top",0)
}
}).mouseout(function(){
$(".box_top_left_99").css("display","none")
$(".box_top_right").css("display","none")
})
</script>
好了,相信看到这里大家都知道该如何去做了,那么现在可以保存查看一下效果了,如果没有做出放大镜效果的程序员也不需要灰心,可以在下方留言询问,或者跟其他人互动来解决都是可以的。
本文由专业的app开发燚轩科技整理发布,如需转载请注明原文作者及出处!
淘过宝的都知道,有些网站需要对商品进行放大镜功能,也就是当鼠标移动到商品上面时,会在旁边出现细节的放大效果,这对于一些商城类网站来说,是一定需要具备的,那么页面放大镜功能是如何来实现的呢?下面就跟大家分享一下。
实现代码:
<style>
html,body{
margin: 0;
padding: 0;
}
.main{
width: 1200px;
margin: 100px auto 0;
display: flex;
}
.box{
width: 400px;
height: 500px;
position: relative;
border: 1px solid red;
display: flex;
flex-flow: column;
justify-content: space-between;
padding: 5px;
}
.box_top{
width: 400px;
height: 400px;
display: flex;
position: relative;
border: 1px solid green;
}
.box_top_left{
width: 400px;
height: 400px;
position: relative;
}
.box_top_left_999{
width: 100%;
height: 100%;
position: absolute;
z-index: 999;
}
.box_top_left_99{
width: 200px;
height: 200px;
position: absolute;
z-index: 99;
background-color: rgb(81, 223, 255);
opacity: 0.5;
display: none;
}
.box_top_left img{
width: 100%;
height: 100%;
}
.box_top_right{
width: 400px;
height: 400px;
overflow: hidden;
position: absolute;
left: 500px;
border: 1px solid red;
display: none;
}
.box_top_right img{
width: 800px;
height: 800px;
position: relative;
display: block;
}
.box_bottom{
width: 400px;
height: 80px;
display: flex;
align-items: center;
border: 1px solid blue;
padding: 1% 0;
}
.box_bottom img{
width: 23%;
height: 100%;
margin: 0 1%;
}
</style>
</head>
<body>
<main>
<div class="main">
<div class="box">
<div class="box_top">
<div class="box_top_left">
<div class="box_top_left_999"></div>
<div class="box_top_left_99"></div>
<img src="imgs/timg.jpg" alt="">
</div>
<div class="box_top_right">
<img src="imgs/timg.jpg" alt="">
</div>
</div>
<div class="box_bottom">
<img src="imgs/timg.jpg" alt="">
<img src="imgs/b.jpg" alt="">
<img src="imgs/c.jpg" alt="">
<img src="imgs/d.jpg" alt="">
</div>
</div>
</div>
</main>
<script>
$(".box_bottom img").each(function(){
$(this).mouseover(function(){
$(".box_top_left img").attr("src",$(this).attr("src"))
$(".box_top_right img").attr("src",$(this).attr("src"))
})
})
$(".box_top_left_999").mousemove(function(e){
var top = e.pageY;
var left = e.pageX;
$(".box_top_left_99").css("display","block")
$(".box_top_right").css("display","block")
var new_left_x = $(this).offset().left+100;
var new_left_d = $(this).offset().left+300;
var img_left = left - new_left_x
img_left = -img_left
img_left = img_left*2
if( left > new_left_x){
if(left < new_left_d){
$(".box_top_left_99").css("left",left - new_left_x)
$(".box_top_right img").css("left",img_left)
}else{
$(".box_top_left_99").css("left",200)
$(".box_top_right img").css("left",-400)
}
}else{
$(".box_top_left_99").css("left",0)
$(".box_top_right img").css("left",0)
}
var new_top_x = $(this).offset().top+100;
var new_top_d = $(this).offset().top+300;
var img_top = top - new_top_x
img_top = -img_top
img_top = img_top*2
if(new_top_x < top){
if(new_top_d>top){
$(".box_top_left_99").css("top",top - new_top_x)
$(".box_top_right img").css("top",img_top)
}else{
$(".box_top_left_99").css("top",200)
$(".box_top_right img").css("top",-400)
}
}else{
$(".box_top_left_99").css("top",0)
$(".box_top_right img").css("top",0)
}
}).mouseout(function(){
$(".box_top_left_99").css("display","none")
$(".box_top_right").css("display","none")
})
</script>
好了,相信看到这里大家都知道该如何去做了,那么现在可以保存查看一下效果了,如果没有做出放大镜效果的程序员也不需要灰心,可以在下方留言询问,或者跟其他人互动来解决都是可以的。
本文由专业的app开发燚轩科技整理发布,如需转载请注明原文作者及出处!
收起阅读 »
新手分享屏蔽全站原生导航条,点back就返回上一页
W2A默认首页没导航条,其他一律新窗体打开页面,下面方法配置下sitemap即可
"pages": [
{
"webviewId": "W2Awwwwwwww",//首页
"matchUrls": [
{
"href": "http://wwwwwwww"
}, {
"href": "http://wwwwwwww/"
}, {
"pathname": "W:/*" //匹配所有页面
}
],
"webviewParameter": {
"titleNView": false,
"statusbar": {
//状态条背景色,
//首页不使用原生导航条,颜色值建议和global->webviewParameter->titleNView->backgroundColor颜色值保持一致
//若首页启用了原生导航条,则建议将首页的statusbar配置为false,这样状态条可以和原生导航条背景色保持一致;
"background": "#f7f7f7"
}
},
"easyConfig":{
"back":{
"history":true //屏蔽了原生导航条允许执行history.back,则返回前一个页面
}
}
W2A默认首页没导航条,其他一律新窗体打开页面,下面方法配置下sitemap即可
"pages": [
{
"webviewId": "W2Awwwwwwww",//首页
"matchUrls": [
{
"href": "http://wwwwwwww"
}, {
"href": "http://wwwwwwww/"
}, {
"pathname": "W:/*" //匹配所有页面
}
],
"webviewParameter": {
"titleNView": false,
"statusbar": {
//状态条背景色,
//首页不使用原生导航条,颜色值建议和global->webviewParameter->titleNView->backgroundColor颜色值保持一致
//若首页启用了原生导航条,则建议将首页的statusbar配置为false,这样状态条可以和原生导航条背景色保持一致;
"background": "#f7f7f7"
}
},
"easyConfig":{
"back":{
"history":true //屏蔽了原生导航条允许执行history.back,则返回前一个页面
}
}

a标签跳转链接问题
在做项目的时候使用a标签,想要跳转到<a href="www.douban.com"></a>,并没有跳转到百度,而是在本页内跳转,找到的原因如下:
href的格式:
1.xxx 相对路径跳转(前面没有/) 跳转到当前目录下的xxx, 如当前URL为xxx.com/aaa/bbb ,则跳转到xxx.com/aaa/xxx
- /xxx 绝对路径跳转(最前面一条/) 跳转到跟目录的xxx,如当前URL为xxx.com/aaa/bbb ,则跳转到xxx.com/xxx
- schema://host/uri 全路径跳转(协议://开头) 跳转到特定的url,host必须有,后面的/uri可以为空
格式不符合全路径跳转的格式,默认就按照第一种处理了
补充一下评论里的情况
//host/uri 的方式(两条杠开头),相当于省略协议,采用同本页面相同的协议
补充一点如果你不想写协议,*可以在路径前写上//*****,如//www.douban.com 这个采用的是与你的网站相同的协议发送请求。
在做项目的时候使用a标签,想要跳转到<a href="www.douban.com"></a>,并没有跳转到百度,而是在本页内跳转,找到的原因如下:
href的格式:
1.xxx 相对路径跳转(前面没有/) 跳转到当前目录下的xxx, 如当前URL为xxx.com/aaa/bbb ,则跳转到xxx.com/aaa/xxx
- /xxx 绝对路径跳转(最前面一条/) 跳转到跟目录的xxx,如当前URL为xxx.com/aaa/bbb ,则跳转到xxx.com/xxx
- schema://host/uri 全路径跳转(协议://开头) 跳转到特定的url,host必须有,后面的/uri可以为空
格式不符合全路径跳转的格式,默认就按照第一种处理了
补充一下评论里的情况
//host/uri 的方式(两条杠开头),相当于省略协议,采用同本页面相同的协议
补充一点如果你不想写协议,*可以在路径前写上//*****,如//www.douban.com 这个采用的是与你的网站相同的协议发送请求。

如何有效实现前端压缩图片并上传功能
随着现在手机的像素越来越高,很多照片动辄几兆甚至十几兆,上传后在服务器端压缩已经越来越不能满足当今的需求。这对于许多技术人员来说,处理起来这样的问题往往不知道该怎么下手,那么燚轩科技下面就跟大家讲解一下如何在前端进行图片压缩后上传到服务器。
以上传单张图片为例,多张图片同理,多嵌套一层循环即可。代码实现如下:
html:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>图片压缩上传</title>
<link href="css/uploadSingleImg.css" rel="stylesheet">
<link rel="stylesheet" type="text/css" href="css/bootstrap.css">
<link href="css/style.css" rel="stylesheet"><!--自己书写input样式-->
<script type="text/javascript" src="js/jquery.min.js"></script>
<script type="text/javascript" src="js/tools.js"></script>
<script type="text/javascript" src="js/pictureHandle.js"></script>
</head>
<body>
<form>
<!--文件选择input-->
<h3>文件选择:</h3>
<input class="btn btn-default" type="file" id="upFile" multiple="multiple" />
<h3>传给后台</h3>
<input class="btn btn-default" type="button" id="upTo" value="提交"/>
<!--后台所要获取的文件base64-->
<h3>后台获取base64文件数据:(一个隐藏域)</h3>
<input id="imgOne" name="imgOne" type="hidden"/>
<!--所选文件压缩前预览-->
<h3>压缩前预览:</h3>
<img src="" id="preview"/>
<div id="yulan1"></div>
<!--所选文件压缩后预览-->
<h3>压缩后预览:</h3>
<img src="" id="nextview"/>
<div id="yulan"></div>
</form>
</body>
</html>
Js:
$(function(){
var _upFile=document.getElementById("upFile");
_upFile.addEventListener("change",function(){
if (_upFile.files.length === 0) {
alert("请选择图片");
return; }
for(var i=0;i<_upFile.files.length;i++){
var oFile = _upFile.files[i];
if(!new RegExp("(jpg|jpeg|png)+","gi").test(oFile.type)){
alert("照片上传:文件类型必须是JPG、JPEG、PNG");
return;
}
var reader = new FileReader();
reader.onload = function(e) {
var base64Img= e.target.result;
//压缩前预览
//$("#preview").attr("src",base64Img);
var str1 = '<img src="'+base64Img+'">';
$('#yulan1').append(str1);
//--执行resize。
var _ir=ImageResizer({
resizeMode:"auto"
,dataSource:base64Img
,dataSourceType:"base64"
,maxWidth:1200 //允许的最大宽度
,maxHeight:600 //允许的最大高度。
,onTmpImgGenerate:function(img){
}
,success:function(resizeImgBase64,canvas){
//压缩后预览
//$("#nextview").attr("src",resizeImgBase64);
var str = '<img src="'+resizeImgBase64+'">';
$('#yulan').append(str);
//赋值到隐藏域传给后台
$('#imgOne').val($('#imgOne').val()+';'+resizeImgBase64.substr(22));
}
,debug:true
});
};
reader.readAsDataURL(oFile);
}
},false);
$('#upTo').on('click',function(){
if (_upFile.files.length === 0) {
alert("请选择图片");
return; }
$.ajax({
url:'server.php',
type:'POST',
dataType:'json',
data:{
imgOne:$('#imgOne').val()
},
success:function(data){
alert(data.msg);
}
});
});
});
php处理:
<?php
$img=trim($_POST['imgOne'],';');
$imgarr=explode(';', $img);
foreach($imgarr as $k=>$v){
//解码
$tmp = base64_decode($v);
//写文件
$filename=time().$k.'.jpg';
$path='./upload/';
file_put_contents($path.$filename, $tmp);
}
$res['msg']='上传成功!';
echo json_encode($res);
该方法实现了PC端文件多选,在手机端可以多次选择上传多张图片的效果,现在已经理解的程序员可以尝试一下了,如果还存在不理解的地方,可以在下方留言讨论。
本文由专业的app开发公司燚轩科技整理发布,如需转载请注明原文作者及出处!
随着现在手机的像素越来越高,很多照片动辄几兆甚至十几兆,上传后在服务器端压缩已经越来越不能满足当今的需求。这对于许多技术人员来说,处理起来这样的问题往往不知道该怎么下手,那么燚轩科技下面就跟大家讲解一下如何在前端进行图片压缩后上传到服务器。
以上传单张图片为例,多张图片同理,多嵌套一层循环即可。代码实现如下:
html:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>图片压缩上传</title>
<link href="css/uploadSingleImg.css" rel="stylesheet">
<link rel="stylesheet" type="text/css" href="css/bootstrap.css">
<link href="css/style.css" rel="stylesheet"><!--自己书写input样式-->
<script type="text/javascript" src="js/jquery.min.js"></script>
<script type="text/javascript" src="js/tools.js"></script>
<script type="text/javascript" src="js/pictureHandle.js"></script>
</head>
<body>
<form>
<!--文件选择input-->
<h3>文件选择:</h3>
<input class="btn btn-default" type="file" id="upFile" multiple="multiple" />
<h3>传给后台</h3>
<input class="btn btn-default" type="button" id="upTo" value="提交"/>
<!--后台所要获取的文件base64-->
<h3>后台获取base64文件数据:(一个隐藏域)</h3>
<input id="imgOne" name="imgOne" type="hidden"/>
<!--所选文件压缩前预览-->
<h3>压缩前预览:</h3>
<img src="" id="preview"/>
<div id="yulan1"></div>
<!--所选文件压缩后预览-->
<h3>压缩后预览:</h3>
<img src="" id="nextview"/>
<div id="yulan"></div>
</form>
</body>
</html>
Js:
$(function(){
var _upFile=document.getElementById("upFile");
_upFile.addEventListener("change",function(){
if (_upFile.files.length === 0) {
alert("请选择图片");
return; }
for(var i=0;i<_upFile.files.length;i++){
var oFile = _upFile.files[i];
if(!new RegExp("(jpg|jpeg|png)+","gi").test(oFile.type)){
alert("照片上传:文件类型必须是JPG、JPEG、PNG");
return;
}
var reader = new FileReader();
reader.onload = function(e) {
var base64Img= e.target.result;
//压缩前预览
//$("#preview").attr("src",base64Img);
var str1 = '<img src="'+base64Img+'">';
$('#yulan1').append(str1);
//--执行resize。
var _ir=ImageResizer({
resizeMode:"auto"
,dataSource:base64Img
,dataSourceType:"base64"
,maxWidth:1200 //允许的最大宽度
,maxHeight:600 //允许的最大高度。
,onTmpImgGenerate:function(img){
}
,success:function(resizeImgBase64,canvas){
//压缩后预览
//$("#nextview").attr("src",resizeImgBase64);
var str = '<img src="'+resizeImgBase64+'">';
$('#yulan').append(str);
//赋值到隐藏域传给后台
$('#imgOne').val($('#imgOne').val()+';'+resizeImgBase64.substr(22));
}
,debug:true
});
};
reader.readAsDataURL(oFile);
}
},false);
$('#upTo').on('click',function(){
if (_upFile.files.length === 0) {
alert("请选择图片");
return; }
$.ajax({
url:'server.php',
type:'POST',
dataType:'json',
data:{
imgOne:$('#imgOne').val()
},
success:function(data){
alert(data.msg);
}
});
});
});
php处理:
<?php
$img=trim($_POST['imgOne'],';');
$imgarr=explode(';', $img);
foreach($imgarr as $k=>$v){
//解码
$tmp = base64_decode($v);
//写文件
$filename=time().$k.'.jpg';
$path='./upload/';
file_put_contents($path.$filename, $tmp);
}
$res['msg']='上传成功!';
echo json_encode($res);
该方法实现了PC端文件多选,在手机端可以多次选择上传多张图片的效果,现在已经理解的程序员可以尝试一下了,如果还存在不理解的地方,可以在下方留言讨论。
本文由专业的app开发公司燚轩科技整理发布,如需转载请注明原文作者及出处!
收起阅读 »
百度地图接口快速调用,一键生成百度地图
对于在网站或者网页之内插入百度地图插件,可能很多编程技术人员都知道如何来做,但是做起来所花费的时间都比较长,那么下面跟大家分享一下如何快速调用百度地图API,一件生成百度地图的方法,这种方法适用于任何的编程语言,所以有兴趣的编程开发者可以保存一下。
body之间源代码如下:
<script type="text/javascript" src="http://api.map.baidu.com/api?key=&v=1.1&services=true"></script>
<div id="map" class="map_cont" style="width:600px;height:400px"></div>
<script type="text/javascript">
//创建和初始化地图函数:
function initMap() {
createMap();//创建地图
setMapEvent();//设置地图事件
addMapControl();//向地图添加控件
addMarker();//向地图中添加marker
}
//创建地图函数:
function createMap() {
var map = new BMap.Map("map");//在百度地图容器中创建一个地图
var point = new BMap.Point(113.610508, 34.766151);//定义一个中心点坐标
map.centerAndZoom(point, 18);//设定地图的中心点和坐标并将地图显示在地图容器中
window.map = map;//将map变量存储在全局
}
//地图事件设置函数:
function setMapEvent() {
map.enableDragging();//启用地图拖拽事件,默认启用(可不写)
map.enableScrollWheelZoom();//启用地图滚轮放大缩小
map.enableDoubleClickZoom();//启用鼠标双击放大,默认启用(可不写)
map.enableKeyboard();//启用键盘上下左右键移动地图
}
//地图控件添加函数:
function addMapControl() {
//向地图中添加缩放控件
var ctrl_nav = new BMap.NavigationControl({ anchor: BMAP_ANCHOR_TOP_LEFT, type: BMAP_NAVIGATION_CONTROL_LARGE });
map.addControl(ctrl_nav);
//向地图中添加缩略图控件
var ctrl_ove = new BMap.OverviewMapControl({ anchor: BMAP_ANCHOR_BOTTOM_RIGHT, isOpen: 1 });
map.addControl(ctrl_ove);
//向地图中添加比例尺控件
var ctrl_sca = new BMap.ScaleControl({ anchor: BMAP_ANCHOR_BOTTOM_LEFT });
map.addControl(ctrl_sca);
}
//标注点数组
var markerArr = [{
title: "公司或地点名称",
content: "地址:详细的地址<br/>电话:公司的联系方式",
point: "113.610508|34.766151",
// point: "118.762938|32.069151",
isOpen: 0,
icon: { w: 23, h: 25, l: 46, t: 21, x: 9, lb: 12 }
}
];
//创建marker
function addMarker() {
for (var i = 0; i < markerArr.length; i++) {
var json = markerArr[i];
var p0 = json.point.split("|")[0];
var p1 = json.point.split("|")[1];
var point = new BMap.Point(p0, p1);
var iconImg = createIcon(json.icon);
var marker = new BMap.Marker(point, { icon: iconImg });
var iw = createInfoWindow(i);
var label = new BMap.Label(json.title, { "offset": new BMap.Size(json.icon.lb - json.icon.x + 10, -20) });
marker.setLabel(label);
map.addOverlay(marker);
label.setStyle({
borderColor: "#808080",
color: "#333",
cursor: "pointer"
});
(function () {
var index = i;
var _iw = createInfoWindow(i);
var _marker = marker;
_marker.addEventListener("click", function () {
this.openInfoWindow(_iw);
});
_iw.addEventListener("open", function () {
_marker.getLabel().hide();
})
_iw.addEventListener("close", function () {
_marker.getLabel().show();
})
label.addEventListener("click", function () {
_marker.openInfoWindow(_iw);
})
if (!!json.isOpen) {
label.hide();
_marker.openInfoWindow(_iw);
}
})()
}
}
//创建InfoWindow
function createInfoWindow(i) {
var json = markerArr[i];
var icon = new BMap.Icon("http://app.baidu.com/map/images/us_mk_icon.jpg", new BMap.Size(json.w, json.h), { imageOffset: new BMap.Size(-json.l, -json.t), infoWindowOffset: new BMap.Size(json.lb + 5, 1), offset: new BMap.Size(json.x, json.h) })
var iw = new BMap.InfoWindow("<b class='iw_poi_title' title='" + json.title + "'>" + json.title + "</b><div class='iw_poi_content'>" + json.content + "</div>");
return iw;
}
//创建一个Icon
function createIcon(json) {
}
initMap();//创建和初始化地图
</script>
相信尝试过之后,各位编程技术人员已经看到效果了,如果有什么好的想法,可以在下方评论区留言,我们互相共同进步。
原文来源app开发燚轩科技官网(http://www.appsaa.com),如需转载请注明原文作者及出处!
对于在网站或者网页之内插入百度地图插件,可能很多编程技术人员都知道如何来做,但是做起来所花费的时间都比较长,那么下面跟大家分享一下如何快速调用百度地图API,一件生成百度地图的方法,这种方法适用于任何的编程语言,所以有兴趣的编程开发者可以保存一下。
body之间源代码如下:
<script type="text/javascript" src="http://api.map.baidu.com/api?key=&v=1.1&services=true"></script>
<div id="map" class="map_cont" style="width:600px;height:400px"></div>
<script type="text/javascript">
//创建和初始化地图函数:
function initMap() {
createMap();//创建地图
setMapEvent();//设置地图事件
addMapControl();//向地图添加控件
addMarker();//向地图中添加marker
}
//创建地图函数:
function createMap() {
var map = new BMap.Map("map");//在百度地图容器中创建一个地图
var point = new BMap.Point(113.610508, 34.766151);//定义一个中心点坐标
map.centerAndZoom(point, 18);//设定地图的中心点和坐标并将地图显示在地图容器中
window.map = map;//将map变量存储在全局
}
//地图事件设置函数:
function setMapEvent() {
map.enableDragging();//启用地图拖拽事件,默认启用(可不写)
map.enableScrollWheelZoom();//启用地图滚轮放大缩小
map.enableDoubleClickZoom();//启用鼠标双击放大,默认启用(可不写)
map.enableKeyboard();//启用键盘上下左右键移动地图
}
//地图控件添加函数:
function addMapControl() {
//向地图中添加缩放控件
var ctrl_nav = new BMap.NavigationControl({ anchor: BMAP_ANCHOR_TOP_LEFT, type: BMAP_NAVIGATION_CONTROL_LARGE });
map.addControl(ctrl_nav);
//向地图中添加缩略图控件
var ctrl_ove = new BMap.OverviewMapControl({ anchor: BMAP_ANCHOR_BOTTOM_RIGHT, isOpen: 1 });
map.addControl(ctrl_ove);
//向地图中添加比例尺控件
var ctrl_sca = new BMap.ScaleControl({ anchor: BMAP_ANCHOR_BOTTOM_LEFT });
map.addControl(ctrl_sca);
}
//标注点数组
var markerArr = [{
title: "公司或地点名称",
content: "地址:详细的地址<br/>电话:公司的联系方式",
point: "113.610508|34.766151",
// point: "118.762938|32.069151",
isOpen: 0,
icon: { w: 23, h: 25, l: 46, t: 21, x: 9, lb: 12 }
}
];
//创建marker
function addMarker() {
for (var i = 0; i < markerArr.length; i++) {
var json = markerArr[i];
var p0 = json.point.split("|")[0];
var p1 = json.point.split("|")[1];
var point = new BMap.Point(p0, p1);
var iconImg = createIcon(json.icon);
var marker = new BMap.Marker(point, { icon: iconImg });
var iw = createInfoWindow(i);
var label = new BMap.Label(json.title, { "offset": new BMap.Size(json.icon.lb - json.icon.x + 10, -20) });
marker.setLabel(label);
map.addOverlay(marker);
label.setStyle({
borderColor: "#808080",
color: "#333",
cursor: "pointer"
});
(function () {
var index = i;
var _iw = createInfoWindow(i);
var _marker = marker;
_marker.addEventListener("click", function () {
this.openInfoWindow(_iw);
});
_iw.addEventListener("open", function () {
_marker.getLabel().hide();
})
_iw.addEventListener("close", function () {
_marker.getLabel().show();
})
label.addEventListener("click", function () {
_marker.openInfoWindow(_iw);
})
if (!!json.isOpen) {
label.hide();
_marker.openInfoWindow(_iw);
}
})()
}
}
//创建InfoWindow
function createInfoWindow(i) {
var json = markerArr[i];
var icon = new BMap.Icon("http://app.baidu.com/map/images/us_mk_icon.jpg", new BMap.Size(json.w, json.h), { imageOffset: new BMap.Size(-json.l, -json.t), infoWindowOffset: new BMap.Size(json.lb + 5, 1), offset: new BMap.Size(json.x, json.h) })
var iw = new BMap.InfoWindow("<b class='iw_poi_title' title='" + json.title + "'>" + json.title + "</b><div class='iw_poi_content'>" + json.content + "</div>");
return iw;
}
//创建一个Icon
function createIcon(json) {
}
initMap();//创建和初始化地图
</script>
相信尝试过之后,各位编程技术人员已经看到效果了,如果有什么好的想法,可以在下方评论区留言,我们互相共同进步。
原文来源app开发燚轩科技官网(http://www.appsaa.com),如需转载请注明原文作者及出处!
收起阅读 »
关于微信支付的那点事
用了一天多时间才把微信支付调起来,中间有一些弯路,把经验分享出来以免后来人浪费时间。
统一下单生成prepayid我就不赘述了,这是最基本的。
在h5调用支付时,最最关键的参数 官方没说明白 微信官方也没说明白。
这是相关的参数。
prepayid(统一下单里返回的标识符),
partnerid(商户号),
appid,
package(微信要求必须有,内容是“Sign=WXPay”),
noncestr(随机数,不适用微信统一下单时返回的,是重新生成一个 关键!!!!),
timestamp(时间戳,十位,注意统一下单里的时间是完整的时间,这里是时间戳,是重新生成一个 关键!!!!),
sign(签名,将上述字段重新签名,而不是用统一下单返回的sign 关键!!!!)。
请注意括号里关键!!!!的内容。
总的说就是调起支付接口需要重新签名。不要使用统一下单里返回的相关内容。
最后说是一下dcloud的文档,老生常谈了比较差。还有论坛里的文档,我看也有调起支付的还有图,但为什么就是不说明白签名
这一步呢,还传上了调起支付的截图。我表示怀疑是否真的成功调起来了。
最后感谢一下https://blog.csdn.net/the_knife/article/details/70141203
用了一天多时间才把微信支付调起来,中间有一些弯路,把经验分享出来以免后来人浪费时间。
统一下单生成prepayid我就不赘述了,这是最基本的。
在h5调用支付时,最最关键的参数 官方没说明白 微信官方也没说明白。
这是相关的参数。
prepayid(统一下单里返回的标识符),
partnerid(商户号),
appid,
package(微信要求必须有,内容是“Sign=WXPay”),
noncestr(随机数,不适用微信统一下单时返回的,是重新生成一个 关键!!!!),
timestamp(时间戳,十位,注意统一下单里的时间是完整的时间,这里是时间戳,是重新生成一个 关键!!!!),
sign(签名,将上述字段重新签名,而不是用统一下单返回的sign 关键!!!!)。
请注意括号里关键!!!!的内容。
总的说就是调起支付接口需要重新签名。不要使用统一下单里返回的相关内容。
最后说是一下dcloud的文档,老生常谈了比较差。还有论坛里的文档,我看也有调起支付的还有图,但为什么就是不说明白签名
这一步呢,还传上了调起支付的截图。我表示怀疑是否真的成功调起来了。
最后感谢一下https://blog.csdn.net/the_knife/article/details/70141203
收起阅读 »
php语言中Excel表格导入数据库的方法详解
在php编程语言中,对于如何在Excel表格中导入数据库的方法是很多编程者比较头疼的一个问题,有些技术人员可能在百度尝试过搜索很多不同的问题,但是给出的答案经过自己测试之后,发现还是行不通,那么对此,燚轩科技也尝试了一下如何在Excel表格中导入数据库,现在将源代码展示给各位技术编程者,大家可以借鉴参考一下。
public function saveexcel(){
require_once('./Thinkphp/Extend/Vendor/PHPExcel-1.8/Classes/PHPExcel.php');
require_once('./Thinkphp/Extend/Vendor/PHPExcel-1.8/Classes/PHPExcel/IOFactory.php');
require_once('./Thinkphp/Extend/Vendor/PHPExcel-1.8/Classes/PHPExcel/Reader/Excel5.php');
//获取表格的大小,限制上传表格的大小5M
// $file_size = $_FILES['myfile']['size'];
// if ($file_size>5*1024*1024) {
// echo "<script>alert('上传失败,上传的表格不能超过5M的大小');history.go(-1);</script>";
// exit();
// }
//限制上传表格类型
$file_type = $_FILES['myfile']['type'];
if ($file_type!='application/vnd.ms-excel') {
echo "<script>alert('上传失败,只能上传excel2003或97-2003的xls格式!');history.go(-1)</script>";
exit();
}
//判断表格是否上传成功
if (is_uploaded_file($_FILES['myfile']['tmp_name'])) {
//以上三步加载phpExcel的类
$objReader = \PHPExcel_IOFactory::createReader('Excel5');//use excel2007 for 2007 format
//接收存在缓存中的excel表格
$filename = $_FILES['myfile']['tmp_name'];
$objPHPExcel = $objReader->load($filename); //$filename可以是上传的表格,或者是指定的表格
$sheet = $objPHPExcel->getSheet(0);
$highestRow = $sheet->getHighestRow(); // 取得总行数
// $highestColumn = $sheet->getHighestColumn(); // 取得总列数
//循环读取excel表格,读取一条,插入一条
//j表示从哪一行开始读取 从第二行开始读取,因为第一行是标题不保存
//$a表示列号
$model=M('user');
$rechargemodel=M('recharge');
$joinmodel=M('joinplan');
for($j=2;$j<=$highestRow;$j++)
{
$name = $objPHPExcel->getActiveSheet()->getCell("B".$j)->getValue();//获取B(姓名)列的值
$tel = $objPHPExcel->getActiveSheet()->getCell("C".$j)->getValue();//获取C(手机号)列的值
$arr['name']=$name;
$arr['tel']=$tel;
$arr['addtime']=time();
$arr['geti']=0;
$res=$model->add($arr);
}
if($res){
success('添加成功',U('userlist'));
}else{
error('操作失败,请稍后再试');
}
}
}
代码导出(不需要引入 任何接口)
public function exportDayInner(){
$model = M("Goodsinfo");
// $innerdata = $mod->select();
$list = $model->order('gid desc')->select();
$smodel = M("Shopinfo");
$gmodel = M("Goodscategory");
foreach ($list as $key => $value) {
$list[$key]['maoli']=floatval($value['price'])-floatval($value['jprice']);
$list[$key]['maolilv']=floatval($list[$key]['maoli'])/floatval($value['price'])*100;
$list[$key]["catename"]=$gmodel->where("id=%d",$value['goodscateid'])->getField("name");
}
$a =['普通商品','休闲专区','特价专区','套餐专区','酒水专区','新品专区','限购','普通商品'];
$b = ['推荐','不推荐'];
$c = ['有','无'];
// echo $mod->getLastSql();exit;
// dump($innerdata);die;
$table = '';
$table .= "<table align='center' border='1' cellpadding'0' cellspacing='0'>
<thead>
<tr>
<th class='name'>序号</th>
<th class='name'>商品名</th>
<th class='name'>商品类型</th>
<th class='name'>商品一级分类</th>
<th class='name'>商品二级分类</th>
<th class='name'>是否推荐</th>
<th class='name'>进价</th>
<th class='name'>售价</th>
<th class='name'>毛利</th>
<th class='name'>毛利率</th>
<th class='name'>条码</th>
<th class='name'>规格</th>
<th class='name'>生产日期</th>
<th class='name'>保质期</th>
<th class='name'>建议零售价</th>
<th class='name'>是否有货</th>
</tr>
</thead>
<tbody>";
foreach ($list as $v) {
$table .= "<tr align='center'>
<td class='name'>{$v['gid']}</td>
<td class='name'>{$v['gname']}</td>
<td class='name'>{$a[$v['type']]}</td>
<td class='name'>{$v['catename']}</td>
<td class='name'>{$v['classify']}</td>
<td class='name'>{$b[$v['like']]}</td>
<td class='name'>{$v['jprice']}</td>
<td class='name'>{$v['price']}/{$v['unity']} </td>
<td class='name'>{$v['maoli']}</td>
<td class='name'>{$v['maolilv']}%</td>
<td class='name'>{$v['borcode']}</td>
<td class='name'>{$v['norms']}</td>
<td class='name'>{$v['ptime']}</td>
<td class='name'>{$v['shelflife']}</td>
<td class='name'>{$v['retail_price']}</td>
<td class='name'>{$c[$v['repertor']]}</td>
</tr>";
}
$table .= "</tbody>
</table>";
//通过header头控制输出excel表格
header("Pragma: public");
header("Expires: 0");
header("Cache-Control:must-revalidate, post-check=0, pre-check=0");
header("Content-Type:application/force-download");
header("Content-Type:application/vnd.ms-execl");
header("Content-Type:application/octet-stream");
header("Content-Type:application/download");
header('Content-Disposition:attachment;filename="商品列表.xls"');
header("Content-Transfer-Encoding:binary");
echo $table;
}
以上就是为各位讲解的如何在Excel表格中导入数据库的具体方法了,希望有不懂的技术人员可以在评论中提出,我们会为您解答。
原文来源燚轩科技官网(http://www.appsaa.com),如需转载请注明原文作者及出处!
在php编程语言中,对于如何在Excel表格中导入数据库的方法是很多编程者比较头疼的一个问题,有些技术人员可能在百度尝试过搜索很多不同的问题,但是给出的答案经过自己测试之后,发现还是行不通,那么对此,燚轩科技也尝试了一下如何在Excel表格中导入数据库,现在将源代码展示给各位技术编程者,大家可以借鉴参考一下。
public function saveexcel(){
require_once('./Thinkphp/Extend/Vendor/PHPExcel-1.8/Classes/PHPExcel.php');
require_once('./Thinkphp/Extend/Vendor/PHPExcel-1.8/Classes/PHPExcel/IOFactory.php');
require_once('./Thinkphp/Extend/Vendor/PHPExcel-1.8/Classes/PHPExcel/Reader/Excel5.php');
//获取表格的大小,限制上传表格的大小5M
// $file_size = $_FILES['myfile']['size'];
// if ($file_size>5*1024*1024) {
// echo "<script>alert('上传失败,上传的表格不能超过5M的大小');history.go(-1);</script>";
// exit();
// }
//限制上传表格类型
$file_type = $_FILES['myfile']['type'];
if ($file_type!='application/vnd.ms-excel') {
echo "<script>alert('上传失败,只能上传excel2003或97-2003的xls格式!');history.go(-1)</script>";
exit();
}
//判断表格是否上传成功
if (is_uploaded_file($_FILES['myfile']['tmp_name'])) {
//以上三步加载phpExcel的类
$objReader = \PHPExcel_IOFactory::createReader('Excel5');//use excel2007 for 2007 format
//接收存在缓存中的excel表格
$filename = $_FILES['myfile']['tmp_name'];
$objPHPExcel = $objReader->load($filename); //$filename可以是上传的表格,或者是指定的表格
$sheet = $objPHPExcel->getSheet(0);
$highestRow = $sheet->getHighestRow(); // 取得总行数
// $highestColumn = $sheet->getHighestColumn(); // 取得总列数
//循环读取excel表格,读取一条,插入一条
//j表示从哪一行开始读取 从第二行开始读取,因为第一行是标题不保存
//$a表示列号
$model=M('user');
$rechargemodel=M('recharge');
$joinmodel=M('joinplan');
for($j=2;$j<=$highestRow;$j++)
{
$name = $objPHPExcel->getActiveSheet()->getCell("B".$j)->getValue();//获取B(姓名)列的值
$tel = $objPHPExcel->getActiveSheet()->getCell("C".$j)->getValue();//获取C(手机号)列的值
$arr['name']=$name;
$arr['tel']=$tel;
$arr['addtime']=time();
$arr['geti']=0;
$res=$model->add($arr);
}
if($res){
success('添加成功',U('userlist'));
}else{
error('操作失败,请稍后再试');
}
}
}
代码导出(不需要引入 任何接口)
public function exportDayInner(){
$model = M("Goodsinfo");
// $innerdata = $mod->select();
$list = $model->order('gid desc')->select();
$smodel = M("Shopinfo");
$gmodel = M("Goodscategory");
foreach ($list as $key => $value) {
$list[$key]['maoli']=floatval($value['price'])-floatval($value['jprice']);
$list[$key]['maolilv']=floatval($list[$key]['maoli'])/floatval($value['price'])*100;
$list[$key]["catename"]=$gmodel->where("id=%d",$value['goodscateid'])->getField("name");
}
$a =['普通商品','休闲专区','特价专区','套餐专区','酒水专区','新品专区','限购','普通商品'];
$b = ['推荐','不推荐'];
$c = ['有','无'];
// echo $mod->getLastSql();exit;
// dump($innerdata);die;
$table = '';
$table .= "<table align='center' border='1' cellpadding'0' cellspacing='0'>
<thead>
<tr>
<th class='name'>序号</th>
<th class='name'>商品名</th>
<th class='name'>商品类型</th>
<th class='name'>商品一级分类</th>
<th class='name'>商品二级分类</th>
<th class='name'>是否推荐</th>
<th class='name'>进价</th>
<th class='name'>售价</th>
<th class='name'>毛利</th>
<th class='name'>毛利率</th>
<th class='name'>条码</th>
<th class='name'>规格</th>
<th class='name'>生产日期</th>
<th class='name'>保质期</th>
<th class='name'>建议零售价</th>
<th class='name'>是否有货</th>
</tr>
</thead>
<tbody>";
foreach ($list as $v) {
$table .= "<tr align='center'>
<td class='name'>{$v['gid']}</td>
<td class='name'>{$v['gname']}</td>
<td class='name'>{$a[$v['type']]}</td>
<td class='name'>{$v['catename']}</td>
<td class='name'>{$v['classify']}</td>
<td class='name'>{$b[$v['like']]}</td>
<td class='name'>{$v['jprice']}</td>
<td class='name'>{$v['price']}/{$v['unity']} </td>
<td class='name'>{$v['maoli']}</td>
<td class='name'>{$v['maolilv']}%</td>
<td class='name'>{$v['borcode']}</td>
<td class='name'>{$v['norms']}</td>
<td class='name'>{$v['ptime']}</td>
<td class='name'>{$v['shelflife']}</td>
<td class='name'>{$v['retail_price']}</td>
<td class='name'>{$c[$v['repertor']]}</td>
</tr>";
}
$table .= "</tbody>
</table>";
//通过header头控制输出excel表格
header("Pragma: public");
header("Expires: 0");
header("Cache-Control:must-revalidate, post-check=0, pre-check=0");
header("Content-Type:application/force-download");
header("Content-Type:application/vnd.ms-execl");
header("Content-Type:application/octet-stream");
header("Content-Type:application/download");
header('Content-Disposition:attachment;filename="商品列表.xls"');
header("Content-Transfer-Encoding:binary");
echo $table;
}
以上就是为各位讲解的如何在Excel表格中导入数据库的具体方法了,希望有不懂的技术人员可以在评论中提出,我们会为您解答。
原文来源燚轩科技官网(http://www.appsaa.com),如需转载请注明原文作者及出处!
收起阅读 »
[payment微信:-1]General errors
1.js代码接入 参考 http://ask.dcloud.net.cn/article/71 代码ok的
2.微信申请开放平台,商户号绑定(开放申请参考https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=8_5)
3.微信后端流程 参考 https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=8_3
4.个人还发现了BUG,在nubia(努比亚)V5.0,Android版本5.1.1中一直返回-100,换个新版手机就可以,Android7的
1.js代码接入 参考 http://ask.dcloud.net.cn/article/71 代码ok的
2.微信申请开放平台,商户号绑定(开放申请参考https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=8_5)
3.微信后端流程 参考 https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=8_3
4.个人还发现了BUG,在nubia(努比亚)V5.0,Android版本5.1.1中一直返回-100,换个新版手机就可以,Android7的
收起阅读 »
mui填坑系列----上拉加载+横向列表(安卓ios兼容),双webview页面弹窗。
大家有没有遇到这样的问题:双webview页面,父页怎么控制子页弹窗?安卓scroll嵌套怎么里面的不滚动了?解决方法见附件哈。真是研究了好久,囧。
大家有没有遇到这样的问题:双webview页面,父页怎么控制子页弹窗?安卓scroll嵌套怎么里面的不滚动了?解决方法见附件哈。真是研究了好久,囧。

个推使用 坑
知道要搞这个,已经一整天了,开始在mui上面找文档,点来点去没找到,终于后来看到有片文章里面开到一个截图。

类似这样的一个图,感觉很熟悉,好吧就是配置文件里面的SDK配置里面,
好吧,从这里点进去看相关的配置信息吧,然后发现上面说的一大通,原理啥的,我真的不关心好吗,我只想知道怎么做才能实现我要的效果,郁闷!!!然后按照文档里面的配置一步一步都好了。
里面说了android平台,由于使用的android来测试的,就只能拿android 说事了,我今天要吐槽的不是这个,这都不是重点,
然后代码就写成这样了
好了,这个时候我就要去发推送了,首先得打包,打了真的是N次。
先登录个推平台,没账号的注册一个就行了。
然后创建应用,按照提示填就对了。应用标识就是应用包名,这里只说android的。
填好了,然后我就去创建推送了,正常不都是这样吗,对吧!
好吧,我就去创建,这里就不截图,好的,填了一系列的东西到最后点了那个“发送预览”。然后弹框->确认。
Ok,这个时候手机收到推送了,消息栏里多了一条消息,我一看成功了,挺高兴啊,然后就是发现我代码里写的监听事件是一个都没执行啊。
然后就照着问题,我找了半天,可郁闷是我了。
然后在看文档,我想说有些说明很重要的,就不能标个重点吗,行吧,怪我太粗心了,
然后我就又去创建推送了,->点开高级设置设置里面有一个透传消息,这个时候就要填内容了,格式呢就按照这样的来啊,不按照格式来是不会走click事件的,亲试!!
{title:'标题',content:'内容',payload:'数据'}
然后点击事件真的生效了,但是有个问题,状态栏先显示的是前面填的标题内容,然后点击了之后又出现了那个‘标准数值格式’,这也不是我要的效果啊,哪有通知显示两次的,
最重要的来了,之前乱点的时候发现,点击创建推送按钮之后,左边菜单还有一项
下面就按照提示填写吧,消息内容按照刚刚的标准模式来。发送预览--》成功!终于成功了!
知道要搞这个,已经一整天了,开始在mui上面找文档,点来点去没找到,终于后来看到有片文章里面开到一个截图。
类似这样的一个图,感觉很熟悉,好吧就是配置文件里面的SDK配置里面,
好吧,从这里点进去看相关的配置信息吧,然后发现上面说的一大通,原理啥的,我真的不关心好吗,我只想知道怎么做才能实现我要的效果,郁闷!!!然后按照文档里面的配置一步一步都好了。
里面说了android平台,由于使用的android来测试的,就只能拿android 说事了,我今天要吐槽的不是这个,这都不是重点,
然后代码就写成这样了
好了,这个时候我就要去发推送了,首先得打包,打了真的是N次。
先登录个推平台,没账号的注册一个就行了。
然后创建应用,按照提示填就对了。应用标识就是应用包名,这里只说android的。
填好了,然后我就去创建推送了,正常不都是这样吗,对吧!
好吧,我就去创建,这里就不截图,好的,填了一系列的东西到最后点了那个“发送预览”。然后弹框->确认。
Ok,这个时候手机收到推送了,消息栏里多了一条消息,我一看成功了,挺高兴啊,然后就是发现我代码里写的监听事件是一个都没执行啊。
然后就照着问题,我找了半天,可郁闷是我了。
然后在看文档,我想说有些说明很重要的,就不能标个重点吗,行吧,怪我太粗心了,
然后我就又去创建推送了,->点开高级设置设置里面有一个透传消息,这个时候就要填内容了,格式呢就按照这样的来啊,不按照格式来是不会走click事件的,亲试!!
{title:'标题',content:'内容',payload:'数据'}
然后点击事件真的生效了,但是有个问题,状态栏先显示的是前面填的标题内容,然后点击了之后又出现了那个‘标准数值格式’,这也不是我要的效果啊,哪有通知显示两次的,
最重要的来了,之前乱点的时候发现,点击创建推送按钮之后,左边菜单还有一项
下面就按照提示填写吧,消息内容按照刚刚的标准模式来。发送预览--》成功!终于成功了! 收起阅读 »

在uniapp中生成二维码
//qrcode.js改的,可以在uniapp中生成二维码
//<text style="font-size:20px;line-height:20px;background-color:#443355;color:#FFFFFF;">{{make_qrcode}}</text>
//var QR = require("../../Common/qrcode.js");
//使用:that.make_qrcode=drawQrcode.api.draw(url,200,200,null,1);
! function(){
// alignment pattern
var adelta=[0,11,15,19,23,27,31,16,18,20,22,24,26,28,20,22,24,24,26,28,28,22,24,24,26,26,28,28,24,24,26,26,26,28,28,24,26,26,26,28,28];
// version block
var vpat=[0xc94,0x5bc,0xa99,0x4d3,0xbf6,0x762,0x847,0x60d,0x928,0xb78,0x45d,0xa17,0x532,0x9a6,0x683,0x8c9,0x7ec,0xec4,0x1e1,0xfab,0x08e,0xc1a,0x33f,0xd75,0x250,0x9d5,0x6f0,0x8ba,0x79f,0xb0b,0x42e,0xa64,0x541,0xc69];
// final format bits with mask: level << 3 | mask
var fmtword=[0x77c4,0x72f3,0x7daa,0x789d,0x662f,0x6318,0x6c41,0x6976,//L
0x5412,0x5125,0x5e7c,0x5b4b,0x45f9,0x40ce,0x4f97,0x4aa0,//M
0x355f,0x3068,0x3f31,0x3a06,0x24b4,0x2183,0x2eda,0x2bed,//Q
0x1689,0x13be,0x1ce7,0x19d0,0x0762,0x0255,0x0d0c,0x083b //H
];
// 4 per version: number of blocks 1,2;data width;ecc width
var eccblocks=[1,0,19,7,1,0,16,10,1,0,13,13,1,0,9,17,1,0,34,10,1,0,28,16,1,0,22,22,1,
0,16,28,1,0,55,15,1,0,44,26,2,0,17,18,2,0,13,22,1,0,80,20,2,0,32,18,2,0,24,26,
4,0,9,16,1,0,108,26,2,0,43,24,2,2,15,18,2,2,11,22,2,0,68,18,4,0,27,16,4,0,19,
24,4,0,15,28,2,0,78,20,4,0,31,18,2,4,14,18,4,1,13,26,2,0,97,24,2,2,38,22,4,2,
18,22,4,2,14,26,2,0,116,30,3,2,36,22,4,4,16,20,4,4,12,24,2,2,68,18,4,1,43,26,
6,2,19,24,6,2,15,28,4,0,81,20,1,4,50,30,4,4,22,28,3,8,12,24,2,2,92,24,6,2,36,
22,4,6,20,26,7,4,14,28,4,0,107,26,8,1,37,22,8,4,20,24,12,4,11,22,3,1,115,30,4,
5,40,24,11,5,16,20,11,5,12,24,5,1,87,22,5,5,41,24,5,7,24,30,11,7,12,24,5,1,98,
24,7,3,45,28,15,2,19,24,3,13,15,30,1,5,107,28,10,1,46,28,1,15,22,28,2,17,14,28,
5,1,120,30,9,4,43,26,17,1,22,28,2,19,14,28,3,4,113,28,3,11,44,26,17,4,21,26,9,
16,13,26,3,5,107,28,3,13,41,26,15,5,24,30,15,10,15,28,4,4,116,28,17,0,42,26,17,
6,22,28,19,6,16,30,2,7,111,28,17,0,46,28,7,16,24,30,34,0,13,24,4,5,121,30,4,14,
47,28,11,14,24,30,16,14,15,30,6,4,117,30,6,14,45,28,11,16,24,30,30,2,16,30,8,4,
106,26,8,13,47,28,7,22,24,30,22,13,15,30,10,2,114,28,19,4,46,28,28,6,22,28,33,4,
16,30,8,4,122,30,22,3,45,28,8,26,23,30,12,28,15,30,3,10,117,30,3,23,45,28,4,31,
24,30,11,31,15,30,7,7,116,30,21,7,45,28,1,37,23,30,19,26,15,30,5,10,115,30,19,10,
47,28,15,25,24,30,23,25,15,30,13,3,115,30,2,29,46,28,42,1,24,30,23,28,15,30,17,0,
115,30,10,23,46,28,10,35,24,30,19,35,15,30,17,1,115,30,14,21,46,28,29,19,24,30,11,
46,15,30,13,6,115,30,14,23,46,28,44,7,24,30,59,1,16,30,12,7,121,30,12,26,47,28,
39,14,24,30,22,41,15,30,6,14,121,30,6,34,47,28,46,10,24,30,2,64,15,30,17,4,122,
30,29,14,46,28,49,10,24,30,24,46,15,30,4,18,122,30,13,32,46,28,48,14,24,30,42,32,
15,30,20,4,117,30,40,7,47,28,43,22,24,30,10,67,15,30,19,6,118,30,18,31,47,28,34,
34,24,30,20,61,15,30
];
// Galois field log table
var glog=[0xff,0x00,0x01,0x19,0x02,0x32,0x1a,0xc6,0x03,0xdf,0x33,0xee,0x1b,0x68,0xc7,0x4b,0x04,
0x64,0xe0,0x0e,0x34,0x8d,0xef,0x81,0x1c,0xc1,0x69,0xf8,0xc8,0x08,0x4c,0x71,0x05,0x8a,0x65,
0x2f,0xe1,0x24,0x0f,0x21,0x35,0x93,0x8e,0xda,0xf0,0x12,0x82,0x45,0x1d,0xb5,0xc2,0x7d,0x6a,
0x27,0xf9,0xb9,0xc9,0x9a,0x09,0x78,0x4d,0xe4,0x72,0xa6,0x06,0xbf,0x8b,0x62,0x66,0xdd,0x30,
0xfd,0xe2,0x98,0x25,0xb3,0x10,0x91,0x22,0x88,0x36,0xd0,0x94,0xce,0x8f,0x96,0xdb,0xbd,0xf1,
0xd2,0x13,0x5c,0x83,0x38,0x46,0x40,0x1e,0x42,0xb6,0xa3,0xc3,0x48,0x7e,0x6e,0x6b,0x3a,0x28,
0x54,0xfa,0x85,0xba,0x3d,0xca,0x5e,0x9b,0x9f,0x0a,0x15,0x79,0x2b,0x4e,0xd4,0xe5,0xac,0x73,
0xf3,0xa7,0x57,0x07,0x70,0xc0,0xf7,0x8c,0x80,0x63,0x0d,0x67,0x4a,0xde,0xed,0x31,0xc5,0xfe,
0x18,0xe3,0xa5,0x99,0x77,0x26,0xb8,0xb4,0x7c,0x11,0x44,0x92,0xd9,0x23,0x20,0x89,0x2e,0x37,
0x3f,0xd1,0x5b,0x95,0xbc,0xcf,0xcd,0x90,0x87,0x97,0xb2,0xdc,0xfc,0xbe,0x61,0xf2,0x56,0xd3,
0xab,0x14,0x2a,0x5d,0x9e,0x84,0x3c,0x39,0x53,0x47,0x6d,0x41,0xa2,0x1f,0x2d,0x43,0xd8,0xb7,
0x7b,0xa4,0x76,0xc4,0x17,0x49,0xec,0x7f,0x0c,0x6f,0xf6,0x6c,0xa1,0x3b,0x52,0x29,0x9d,0x55,
0xaa,0xfb,0x60,0x86,0xb1,0xbb,0xcc,0x3e,0x5a,0xcb,0x59,0x5f,0xb0,0x9c,0xa9,0xa0,0x51,0x0b,
0xf5,0x16,0xeb,0x7a,0x75,0x2c,0xd7,0x4f,0xae,0xd5,0xe9,0xe6,0xe7,0xad,0xe8,0x74,0xd6,0xf4,
0xea,0xa8,0x50,0x58,0xaf
];
// Galios field exponent table
var gexp=[0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80,0x1d,0x3a,0x74,0xe8,0xcd,0x87,0x13,0x26,0x4c,
0x98,0x2d,0x5a,0xb4,0x75,0xea,0xc9,0x8f,0x03,0x06,0x0c,0x18,0x30,0x60,0xc0,0x9d,0x27,0x4e,
0x9c,0x25,0x4a,0x94,0x35,0x6a,0xd4,0xb5,0x77,0xee,0xc1,0x9f,0x23,0x46,0x8c,0x05,0x0a,0x14,
0x28,0x50,0xa0,0x5d,0xba,0x69,0xd2,0xb9,0x6f,0xde,0xa1,0x5f,0xbe,0x61,0xc2,0x99,0x2f,0x5e,
0xbc,0x65,0xca,0x89,0x0f,0x1e,0x3c,0x78,0xf0,0xfd,0xe7,0xd3,0xbb,0x6b,0xd6,0xb1,0x7f,0xfe,
0xe1,0xdf,0xa3,0x5b,0xb6,0x71,0xe2,0xd9,0xaf,0x43,0x86,0x11,0x22,0x44,0x88,0x0d,0x1a,0x34,
0x68,0xd0,0xbd,0x67,0xce,0x81,0x1f,0x3e,0x7c,0xf8,0xed,0xc7,0x93,0x3b,0x76,0xec,0xc5,0x97,
0x33,0x66,0xcc,0x85,0x17,0x2e,0x5c,0xb8,0x6d,0xda,0xa9,0x4f,0x9e,0x21,0x42,0x84,0x15,0x2a,
0x54,0xa8,0x4d,0x9a,0x29,0x52,0xa4,0x55,0xaa,0x49,0x92,0x39,0x72,0xe4,0xd5,0xb7,0x73,0xe6,
0xd1,0xbf,0x63,0xc6,0x91,0x3f,0x7e,0xfc,0xe5,0xd7,0xb3,0x7b,0xf6,0xf1,0xff,0xe3,0xdb,0xab,
0x4b,0x96,0x31,0x62,0xc4,0x95,0x37,0x6e,0xdc,0xa5,0x57,0xae,0x41,0x82,0x19,0x32,0x64,0xc8,
0x8d,0x07,0x0e,0x1c,0x38,0x70,0xe0,0xdd,0xa7,0x53,0xa6,0x51,0xa2,0x59,0xb2,0x79,0xf2,0xf9,
0xef,0xc3,0x9b,0x2b,0x56,0xac,0x45,0x8a,0x09,0x12,0x24,0x48,0x90,0x3d,0x7a,0xf4,0xf5,0xf7,
0xf3,0xfb,0xeb,0xcb,0x8b,0x0b,0x16,0x2c,0x58,0xb0,0x7d,0xfa,0xe9,0xcf,0x83,0x1b,0x36,0x6c,
0xd8,0xad,0x47,0x8e,0x00
];
// Working buffers:
// data input and ecc append,image working buffer,fixed part of image,run lengths for badness
var strinbuf=[],eccbuf=[],qrframe=[],framask=[],rlens=[];
// Control values-width is based on version,last 4 are from table.
var version,width,neccblk1,neccblk2,datablkw,eccblkwid;
var ecclevel=2;
// set bit to indicate cell in qrframe is immutable. symmetric around diagonal
function setmask(x,y){
var bt;
if(x>y){bt=x;x=y;y=bt;}
bt=y;bt*= y;bt+=y;bt >>= 1;bt+=x;framask[bt]=1;
}
// enter alignment pattern-black to qrframe,white to mask(later black frame merged to mask)
function putalign(x,y){
var j;
qrframe[x+width* y]=1;
for (j = -2; j < 2; j++){
qrframe[x + j + width * (y - 2)] = 1;qrframe[x - 2 + width * (y + j + 1)] = 1;qrframe[x + 2 + width * (y + j)] = 1;qrframe[x + j + 1 + width * (y + 2)] = 1;
}
for(j=0;j<2;j++){
setmask(x-1,y+j);setmask(x+1,y-j);setmask(x-j,y-1);setmask(x+j,y+1);
}
}
//========================================================================
// Reed Solomon error correction
// exponentiation mod N
function modnn(x){
while(x >= 255){x -= 255;x=(x >> 8) +(x & 255);}
return x;
}
var genpoly=[];
// Calculate and append ECC data to data block. Block is in strinbuf,indexes to buffers given.
function appendrs(data,dlen,ecbuf,eclen){
var i,j,fb;
for(i=0;i<eclen;i++){strinbuf[ecbuf+i]=0;}
for(i=0;i<dlen;i++){
fb=glog[strinbuf[data+i] ^ strinbuf[ecbuf]];
if(fb != 255){
for(j=1;j<eclen;j++){strinbuf[ecbuf+j-1]=strinbuf[ecbuf+j] ^ gexp[modnn(fb+genpoly[eclen-j])];}
}else{
for(j=ecbuf;j<ecbuf+eclen;j++){strinbuf[j]=strinbuf[j+1];}
}
strinbuf[ecbuf+eclen-1]=fb == 255 ? 0 : gexp[modnn(fb+genpoly[0])];
}
}
//========================================================================
// Frame data insert following the path rules
// check mask-since symmetrical use half.
function ismasked(x,y){
var bt;
if(x>y){bt=x;x=y;y=bt;}
bt=y;bt+=y* y;bt >>= 1;bt+=x;
return framask[bt];
}
//========================================================================
// Apply the selected mask out of the 8.
function applymask(m){
var x,y,r3x,r3y;
switch(m){
case 0:
for(y=0;y<width;y++){
for(x=0;x<width;x++){
if(!(x+y & 1) && !ismasked(x,y)){qrframe[x+y* width] ^= 1;}
}
}
break;
case 1:
for(y=0;y<width;y++){
for(x=0;x<width;x++){
if(!(y & 1) && !ismasked(x,y)){qrframe[x+y* width] ^= 1;}
}
}
break;
case 2:
for(y=0;y<width;y++){
for(r3x=0,x=0;x<width;x++,r3x++){
if(r3x == 3){r3x=0;}
if(!r3x && !ismasked(x,y)){ qrframe[x+y* width] ^= 1;}
}
}
break;
case 3:
for(r3y=0,y=0;y<width;y++,r3y++){
if(r3y == 3){r3y=0;}
for(r3x=r3y,x=0;x<width;x++,r3x++){
if(r3x == 3){r3x=0;}
if(!r3x && !ismasked(x,y)){qrframe[x+y* width] ^= 1;}
}
}
break;
case 4:
for(y=0;y<width;y++){
for(r3x=0,r3y=y >> 1 & 1,x=0;x<width;x++,r3x++){
if(r3x == 3){r3x=0;r3y=!r3y;}
if(!r3y && !ismasked(x,y)){qrframe[x+y* width] ^= 1;}
}
}
break;
case 5:
for(r3y=0,y=0;y<width;y++,r3y++){
if(r3y == 3){r3y=0;}
for(r3x=0,x=0;x<width;x++,r3x++){
if(r3x == 3){r3x=0;}
if(!(x & y & 1)+!(!r3x | !r3y) && !ismasked(x,y)){qrframe[x+y* width] ^= 1;}
}
}
break;
case 6:
for(r3y=0,y=0;y<width;y++,r3y++){
if(r3y == 3){r3y=0;}
for(r3x=0,x=0;x<width;x++,r3x++){
if(r3x == 3){r3x=0;}
if(!((x & y & 1) +(r3x && r3x == r3y) & 1) && !ismasked(x,y)){qrframe[x+y* width] ^= 1;}
}
}
break;
case 7:
for(r3y=0,y=0;y<width;y++,r3y++){
if(r3y == 3){r3y=0;}
for(r3x=0,x=0;x<width;x++,r3x++){
if(r3x == 3){r3x=0;}
if(!((r3x && r3x == r3y) +(x+y & 1) & 1) && !ismasked(x,y)){qrframe[x+y* width] ^= 1;}
}
}
break;
}
return;
}
// Badness coefficients.
var N1=3,N2=3,N3=40,N4=10;
// Using the table of the length of each run,calculate the amount of bad image
//-long runs or those that look like finders;called twice,once each for X and Y
function badruns(length){
var i;
var runsbad=0;
for(i=0;i <= length;i++){if(rlens[i] >= 5){runsbad+=N1+rlens[i]-5;}}
// BwBBBwB as in finder
for(i=3;i<length-1;i+=2){
if(rlens[i-2] == rlens[i+2] && rlens[i+2] == rlens[i-1] && rlens[i-1] == rlens[i+1] && rlens[i-1]* 3 == rlens[i] &&(rlens[i-3] == 0 || i+3>length || rlens[i-3]* 3 >= rlens[i]* 4 || rlens[i+3]* 3 >= rlens[i]* 4)){runsbad+=N3;}
}
return runsbad;
}
// Calculate how bad the masked image is-blocks,imbalance,runs,or finders.
function badcheck(){
var x,y,h,b,b1;
var thisbad=0;
var bw=0;
// blocks of same color.
for(y=0;y<width-1;y++){
for(x=0;x<width-1;x++){
if(qrframe[x+width* y] && qrframe[x+1+width* y] && qrframe[x+width*(y+1)] && qrframe[x +1+width*(y+1)] || !(qrframe[x+width* y] || qrframe[x+1+width* y] || qrframe[x+width*(y+1)] || qrframe[x +1+width*(y+1)])){
thisbad+=N2;
}
}
}
// X runs
for(y=0;y<width;y++){
rlens[0]=0;
for(h=b=x=0;x<width;x++){
if((b1=qrframe[x+width* y]) == b){rlens[h]++;}
else {rlens[++h]=1;}
b=b1;bw+=b ? 1 : -1;
}
thisbad+=badruns(h);
}
// black/white imbalance
if(bw<0){bw=-bw;}
var big=bw;
var count=0;
big+=big << 2;
big <<= 1;
while(big>width* width){big -= width* width,count++;}
thisbad+=count* N4;
// Y runs
for(x=0;x<width;x++){
rlens[0]=0;
for(h=b=y=0;y<width;y++){
if((b1=qrframe[x+width* y]) == b){rlens[h]++;}
else {rlens[++h]=1;}
b=b1;
}
thisbad+=badruns(h);
}
return thisbad;
}
function genframe(instring){
var x,y,k,t,v,i,j,m;
// find the smallest version that fits the string
t=instring.length;
version=0;
do {
version++;
k=(ecclevel-1)* 4 +(version-1)* 16;
neccblk1=eccblocks[k++];
neccblk2=eccblocks[k++];
datablkw=eccblocks[k++];
eccblkwid=eccblocks[k];
k=datablkw*(neccblk1+neccblk2)+neccblk2-3 +(version <= 9);
if(t <= k){break;}
} while(version<40);
// FIXME-insure that it fits insted of being truncated
width=17+4* version;
// allocate,clear and setup data structures
v=datablkw +(datablkw+eccblkwid)*(neccblk1+neccblk2)+neccblk2;
for(t=0;t<v;t++){eccbuf[t]=0;}
strinbuf=instring.slice(0);
for(t=0;t<width* width;t++){qrframe[t]=0;}
for(t=0;t <(width*(width+1)+1)/2;t++){framask[t]=0;}
// insert finders-black to frame,white to mask
for(t=0;t<3;t++){
k=0;y=0;
if(t == 1){k=width-7;}
if(t == 2){y=width-7;}
qrframe[y+3+width*(k+3)]=1;
for(x=0;x<6;x++){
qrframe[y+x+width* k]=1;qrframe[y+width*(k+x+1)]=1;qrframe[y+6+width*(k+x)]=1;qrframe[y+x+1+width*(k+6)]=1;
}
for(x=1;x<5;x++){
setmask(y+x,k+1);setmask(y+1,k+x+1);setmask(y+5,k+x);setmask(y+x+1,k+5);
}
for(x=2;x<4;x++){
qrframe[y+x+width*(k+2)]=1;qrframe[y+2+width*(k+x+1)]=1;qrframe[y+4+width*(k+x)]=1;qrframe[y+x+1+width*(k+4)]=1;
}
}
// alignment blocks
if(version>1){
t=adelta[version];
y=width-7;
for(;;){
x=width-7;
while(x>t-3){
putalign(x,y);if(x<t){break;}x -= t;
}
if(y <= t+9){ break;}
y -= t;putalign(6,y);putalign(y,6);
}
}
// single black
qrframe[8+width*(width-8)]=1;
// timing gap-mask only
for(y=0;y<7;y++){
setmask(7,y);setmask(width-8,y);setmask(7,y+width-7);
}
for(x=0;x<8;x++){
setmask(x,7);setmask(x+width-8,7);setmask(x,width-8);
}
// reserve mask-format area
for(x=0;x<9;x++){setmask(x,8);}
for(x=0;x<8;x++){
setmask(x+width-8,8);
setmask(8,x);
}
for(y=0;y<7;y++){setmask(8,y+width-7);}
// timing row/col
for(x=0;x<width-14;x++){
if(x & 1){setmask(8+x,6);setmask(6,8+x);}
else{qrframe[8+x+width* 6]=1;qrframe[6+width*(8+x)]=1;}
}
// version block
if(version>6){
t=vpat[version-7];k=17;
for(x=0;x<6;x++){
for(y=0;y<3;y++,k--){
if(1 &(k>11 ? version >> k-12 : t >> k)){
qrframe[5-x+width*(2-y+width-11)]=1;qrframe[2-y+width-11+width*(5-x)]=1;
}else{
setmask(5-x,2-y+width-11);setmask(2-y+width-11,5-x);
}
}
}
}
// sync mask bits-only set above for white spaces,so add in black bits
for(y=0;y<width;y++){for(x=0;x <= y;x++){if(qrframe[x+width* y]){setmask(x,y);}}}
// convert string to bitstream
// 8 bit data to QR-coded 8 bit data(numeric or alphanum,or kanji not supported)
v=strinbuf.length;
// string to array
for(i=0;i<v;i++){ eccbuf[i]=strinbuf.charCodeAt(i);}
strinbuf=eccbuf.slice(0);
// calculate max string length
x=datablkw*(neccblk1+neccblk2)+neccblk2;
if(v >= x-2){v=x-2;if(version>9){ v--;}}
// shift and repack to insert length prefix
i=v;
if(version>9){
strinbuf[i+2]=0;strinbuf[i+3]=0;
while(i--){t=strinbuf[i];strinbuf[i+3] |= 255 & t << 4;strinbuf[i+2]=t >> 4;}
strinbuf[2] |= 255 & v << 4;strinbuf[1]=v >> 4;strinbuf[0]=0x40 | v >> 12;
}else{
strinbuf[i+1]=0;strinbuf[i+2]=0;
while(i--){t=strinbuf[i];strinbuf[i+2] |= 255 & t << 4;strinbuf[i+1]=t >> 4;}
strinbuf[1] |= 255 & v << 4;strinbuf[0]=0x40 | v >> 4;
}
// fill to end with pad pattern
i=v+3 -(version<10);
while(i<x){
strinbuf[i++]=0xec;
// buffer has room if(i == x) break;
strinbuf[i++]=0x11;
}
// calculate and append ECC
// calculate generator polynomial
genpoly[0]=1;
for(i=0;i<eccblkwid;i++){
genpoly[i+1]=1;
for(j=i;j>0;j--){ genpoly[j]=genpoly[j] ? genpoly[j-1] ^ gexp[modnn(glog[genpoly[j]]+i)] : genpoly[j-1];}
genpoly[0]=gexp[modnn(glog[genpoly[0]]+i)];
}
for(i=0;i <= eccblkwid;i++){genpoly[i]=glog[genpoly[i]];}// use logs for genpoly[] to save calc step
// append ecc to data buffer
k=x;y=0;
for(i=0;i<neccblk1;i++){appendrs(y,datablkw,k,eccblkwid);y+=datablkw;k+=eccblkwid;}
for(i=0;i<neccblk2;i++){appendrs(y,datablkw+1,k,eccblkwid);y+=datablkw+1;k+=eccblkwid;}
// interleave blocks
y=0;
for(i=0;i<datablkw;i++){
for(j=0;j<neccblk1;j++){eccbuf[y++]=strinbuf[i+j* datablkw];}
for(j=0;j<neccblk2;j++){eccbuf[y++]=strinbuf[neccblk1* datablkw+i+j*(datablkw+1)];}
}
for(j=0;j<neccblk2;j++){eccbuf[y++]=strinbuf[neccblk1* datablkw+i+j*(datablkw+1)];}
for(i=0;i<eccblkwid;i++){
for(j=0;j<neccblk1+neccblk2;j++){ eccbuf[y++]=strinbuf[x+i+j* eccblkwid];}
}
strinbuf=eccbuf;
// pack bits into frame avoiding masked area.
x=y=width-1;
k=v=1;// up,minus
/* inteleaved data and ecc codes*/
m=(datablkw+eccblkwid)*(neccblk1+neccblk2)+neccblk2;
for(i=0;i<m;i++){
t=strinbuf[i];
for(j=0;j<8;j++,t <<= 1){
if(0x80 & t){qrframe[x+width* y]=1;}
do {
// find next fill position
if(v){x--;}
else {
x++;
if(k){if(y != 0){y--;}else {x -= 2;k=!k;if(x == 6){x--;y=9;}}}
else{if(y != width-1){ y++;}else {x -= 2;k=!k;if(x == 6){x--;y -= 8;}}}
}
v=!v;
} while(ismasked(x,y));
}
}
// save pre-mask copy of frame
strinbuf=qrframe.slice(0);
t=0;// best
y=30000;// demerit
// for instead of while since in original arduino code
// if an early mask was "good enough" it wouldn't try for a better one
// since they get more complex and take longer.
for(k=0;k<8;k++){
applymask(k);// returns black-white imbalance
x=badcheck();
if(x<y){// current mask better than previous best?
y=x;t=k;
}
if(t == 7){break;}// don't increment i to a void redoing mask
qrframe=strinbuf.slice(0);// reset for next pass
}
if(t != k){ // redo best mask-none good enough,last wasn't t
applymask(t);
}
// add in final mask/ecclevel bytes
y=fmtword[t +(ecclevel-1 << 3)];
// low byte
for(k=0;k<8;k++,y >>= 1){
if(y & 1){qrframe[width-1-k+width* 8]=1;if(k<6){qrframe[8+width* k]=1;}else {qrframe[8+width*(k+1)]=1;}}
}
// high byte
for(k=0;k<7;k++,y >>= 1){
if(y & 1){qrframe[8+width*(width-7+k)]=1;if(k){qrframe[6-k+width* 8]=1;}else {qrframe[7+width* 8]=1;}}
}
return qrframe;
}
var api={
get ecclevel(){return ecclevel;},
set ecclevel(val){ecclevel=val;},
get size(){return _size;},
set size(val){_size=val;},
getFrame: function(string){return genframe(string);},
//这里的utf16to8(str)是对Text中的字符串进行转码,让其支持中文
utf16to8: function(str){
var out,i,len,c;
out="";len=str.length;
for(i=0;i<len;i++){
c=str.charCodeAt(i);
if(c >= 0x0001 && c <= 0x007F){
out+=str.charAt(i);
}else if(c>0x07FF){
out+=String.fromCharCode(0xE0 | c >> 12 & 0x0F);out+=String.fromCharCode(0x80 | c >> 6 & 0x3F);out+=String.fromCharCode(0x80 | c >> 0 & 0x3F);
}else{
out+=String.fromCharCode(0xC0 | c >> 6 & 0x1F);out+=String.fromCharCode(0x80 | c >> 0 & 0x3F);
}
}
return out;
},
/*新增$this参数,传入组件的this,兼容在组件中生成*/
drawQrcode: function(str,cavW,cavH,$this,ecc){
var that=this;
ecclevel=ecc || ecclevel;
var size=Math.min(cavW,cavH);
str=that.utf16to8(str);//增加中文显示
var frame=that.getFrame(str),
px=Math.round(size /(width+8));
var roundedSize=px*(width+8),offset=Math.floor((size-roundedSize)/2);
size=roundedSize;
var ctx='';
for(var i=0;i<width;i++){
if(i!=0){ctx+='\n';}
for(var j=0;j<width;j++){
if(frame[j* width+i]){ctx+=' ';}
else{
ctx+='■';
}//■●◆★■▲
}
}
ctx+='';
return ctx;
}
};
module.exports={api};
}();
//qrcode.js改的,可以在uniapp中生成二维码
//<text style="font-size:20px;line-height:20px;background-color:#443355;color:#FFFFFF;">{{make_qrcode}}</text>
//var QR = require("../../Common/qrcode.js");
//使用:that.make_qrcode=drawQrcode.api.draw(url,200,200,null,1);
! function(){
// alignment pattern
var adelta=[0,11,15,19,23,27,31,16,18,20,22,24,26,28,20,22,24,24,26,28,28,22,24,24,26,26,28,28,24,24,26,26,26,28,28,24,26,26,26,28,28];
// version block
var vpat=[0xc94,0x5bc,0xa99,0x4d3,0xbf6,0x762,0x847,0x60d,0x928,0xb78,0x45d,0xa17,0x532,0x9a6,0x683,0x8c9,0x7ec,0xec4,0x1e1,0xfab,0x08e,0xc1a,0x33f,0xd75,0x250,0x9d5,0x6f0,0x8ba,0x79f,0xb0b,0x42e,0xa64,0x541,0xc69];
// final format bits with mask: level << 3 | mask
var fmtword=[0x77c4,0x72f3,0x7daa,0x789d,0x662f,0x6318,0x6c41,0x6976,//L
0x5412,0x5125,0x5e7c,0x5b4b,0x45f9,0x40ce,0x4f97,0x4aa0,//M
0x355f,0x3068,0x3f31,0x3a06,0x24b4,0x2183,0x2eda,0x2bed,//Q
0x1689,0x13be,0x1ce7,0x19d0,0x0762,0x0255,0x0d0c,0x083b //H
];
// 4 per version: number of blocks 1,2;data width;ecc width
var eccblocks=[1,0,19,7,1,0,16,10,1,0,13,13,1,0,9,17,1,0,34,10,1,0,28,16,1,0,22,22,1,
0,16,28,1,0,55,15,1,0,44,26,2,0,17,18,2,0,13,22,1,0,80,20,2,0,32,18,2,0,24,26,
4,0,9,16,1,0,108,26,2,0,43,24,2,2,15,18,2,2,11,22,2,0,68,18,4,0,27,16,4,0,19,
24,4,0,15,28,2,0,78,20,4,0,31,18,2,4,14,18,4,1,13,26,2,0,97,24,2,2,38,22,4,2,
18,22,4,2,14,26,2,0,116,30,3,2,36,22,4,4,16,20,4,4,12,24,2,2,68,18,4,1,43,26,
6,2,19,24,6,2,15,28,4,0,81,20,1,4,50,30,4,4,22,28,3,8,12,24,2,2,92,24,6,2,36,
22,4,6,20,26,7,4,14,28,4,0,107,26,8,1,37,22,8,4,20,24,12,4,11,22,3,1,115,30,4,
5,40,24,11,5,16,20,11,5,12,24,5,1,87,22,5,5,41,24,5,7,24,30,11,7,12,24,5,1,98,
24,7,3,45,28,15,2,19,24,3,13,15,30,1,5,107,28,10,1,46,28,1,15,22,28,2,17,14,28,
5,1,120,30,9,4,43,26,17,1,22,28,2,19,14,28,3,4,113,28,3,11,44,26,17,4,21,26,9,
16,13,26,3,5,107,28,3,13,41,26,15,5,24,30,15,10,15,28,4,4,116,28,17,0,42,26,17,
6,22,28,19,6,16,30,2,7,111,28,17,0,46,28,7,16,24,30,34,0,13,24,4,5,121,30,4,14,
47,28,11,14,24,30,16,14,15,30,6,4,117,30,6,14,45,28,11,16,24,30,30,2,16,30,8,4,
106,26,8,13,47,28,7,22,24,30,22,13,15,30,10,2,114,28,19,4,46,28,28,6,22,28,33,4,
16,30,8,4,122,30,22,3,45,28,8,26,23,30,12,28,15,30,3,10,117,30,3,23,45,28,4,31,
24,30,11,31,15,30,7,7,116,30,21,7,45,28,1,37,23,30,19,26,15,30,5,10,115,30,19,10,
47,28,15,25,24,30,23,25,15,30,13,3,115,30,2,29,46,28,42,1,24,30,23,28,15,30,17,0,
115,30,10,23,46,28,10,35,24,30,19,35,15,30,17,1,115,30,14,21,46,28,29,19,24,30,11,
46,15,30,13,6,115,30,14,23,46,28,44,7,24,30,59,1,16,30,12,7,121,30,12,26,47,28,
39,14,24,30,22,41,15,30,6,14,121,30,6,34,47,28,46,10,24,30,2,64,15,30,17,4,122,
30,29,14,46,28,49,10,24,30,24,46,15,30,4,18,122,30,13,32,46,28,48,14,24,30,42,32,
15,30,20,4,117,30,40,7,47,28,43,22,24,30,10,67,15,30,19,6,118,30,18,31,47,28,34,
34,24,30,20,61,15,30
];
// Galois field log table
var glog=[0xff,0x00,0x01,0x19,0x02,0x32,0x1a,0xc6,0x03,0xdf,0x33,0xee,0x1b,0x68,0xc7,0x4b,0x04,
0x64,0xe0,0x0e,0x34,0x8d,0xef,0x81,0x1c,0xc1,0x69,0xf8,0xc8,0x08,0x4c,0x71,0x05,0x8a,0x65,
0x2f,0xe1,0x24,0x0f,0x21,0x35,0x93,0x8e,0xda,0xf0,0x12,0x82,0x45,0x1d,0xb5,0xc2,0x7d,0x6a,
0x27,0xf9,0xb9,0xc9,0x9a,0x09,0x78,0x4d,0xe4,0x72,0xa6,0x06,0xbf,0x8b,0x62,0x66,0xdd,0x30,
0xfd,0xe2,0x98,0x25,0xb3,0x10,0x91,0x22,0x88,0x36,0xd0,0x94,0xce,0x8f,0x96,0xdb,0xbd,0xf1,
0xd2,0x13,0x5c,0x83,0x38,0x46,0x40,0x1e,0x42,0xb6,0xa3,0xc3,0x48,0x7e,0x6e,0x6b,0x3a,0x28,
0x54,0xfa,0x85,0xba,0x3d,0xca,0x5e,0x9b,0x9f,0x0a,0x15,0x79,0x2b,0x4e,0xd4,0xe5,0xac,0x73,
0xf3,0xa7,0x57,0x07,0x70,0xc0,0xf7,0x8c,0x80,0x63,0x0d,0x67,0x4a,0xde,0xed,0x31,0xc5,0xfe,
0x18,0xe3,0xa5,0x99,0x77,0x26,0xb8,0xb4,0x7c,0x11,0x44,0x92,0xd9,0x23,0x20,0x89,0x2e,0x37,
0x3f,0xd1,0x5b,0x95,0xbc,0xcf,0xcd,0x90,0x87,0x97,0xb2,0xdc,0xfc,0xbe,0x61,0xf2,0x56,0xd3,
0xab,0x14,0x2a,0x5d,0x9e,0x84,0x3c,0x39,0x53,0x47,0x6d,0x41,0xa2,0x1f,0x2d,0x43,0xd8,0xb7,
0x7b,0xa4,0x76,0xc4,0x17,0x49,0xec,0x7f,0x0c,0x6f,0xf6,0x6c,0xa1,0x3b,0x52,0x29,0x9d,0x55,
0xaa,0xfb,0x60,0x86,0xb1,0xbb,0xcc,0x3e,0x5a,0xcb,0x59,0x5f,0xb0,0x9c,0xa9,0xa0,0x51,0x0b,
0xf5,0x16,0xeb,0x7a,0x75,0x2c,0xd7,0x4f,0xae,0xd5,0xe9,0xe6,0xe7,0xad,0xe8,0x74,0xd6,0xf4,
0xea,0xa8,0x50,0x58,0xaf
];
// Galios field exponent table
var gexp=[0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80,0x1d,0x3a,0x74,0xe8,0xcd,0x87,0x13,0x26,0x4c,
0x98,0x2d,0x5a,0xb4,0x75,0xea,0xc9,0x8f,0x03,0x06,0x0c,0x18,0x30,0x60,0xc0,0x9d,0x27,0x4e,
0x9c,0x25,0x4a,0x94,0x35,0x6a,0xd4,0xb5,0x77,0xee,0xc1,0x9f,0x23,0x46,0x8c,0x05,0x0a,0x14,
0x28,0x50,0xa0,0x5d,0xba,0x69,0xd2,0xb9,0x6f,0xde,0xa1,0x5f,0xbe,0x61,0xc2,0x99,0x2f,0x5e,
0xbc,0x65,0xca,0x89,0x0f,0x1e,0x3c,0x78,0xf0,0xfd,0xe7,0xd3,0xbb,0x6b,0xd6,0xb1,0x7f,0xfe,
0xe1,0xdf,0xa3,0x5b,0xb6,0x71,0xe2,0xd9,0xaf,0x43,0x86,0x11,0x22,0x44,0x88,0x0d,0x1a,0x34,
0x68,0xd0,0xbd,0x67,0xce,0x81,0x1f,0x3e,0x7c,0xf8,0xed,0xc7,0x93,0x3b,0x76,0xec,0xc5,0x97,
0x33,0x66,0xcc,0x85,0x17,0x2e,0x5c,0xb8,0x6d,0xda,0xa9,0x4f,0x9e,0x21,0x42,0x84,0x15,0x2a,
0x54,0xa8,0x4d,0x9a,0x29,0x52,0xa4,0x55,0xaa,0x49,0x92,0x39,0x72,0xe4,0xd5,0xb7,0x73,0xe6,
0xd1,0xbf,0x63,0xc6,0x91,0x3f,0x7e,0xfc,0xe5,0xd7,0xb3,0x7b,0xf6,0xf1,0xff,0xe3,0xdb,0xab,
0x4b,0x96,0x31,0x62,0xc4,0x95,0x37,0x6e,0xdc,0xa5,0x57,0xae,0x41,0x82,0x19,0x32,0x64,0xc8,
0x8d,0x07,0x0e,0x1c,0x38,0x70,0xe0,0xdd,0xa7,0x53,0xa6,0x51,0xa2,0x59,0xb2,0x79,0xf2,0xf9,
0xef,0xc3,0x9b,0x2b,0x56,0xac,0x45,0x8a,0x09,0x12,0x24,0x48,0x90,0x3d,0x7a,0xf4,0xf5,0xf7,
0xf3,0xfb,0xeb,0xcb,0x8b,0x0b,0x16,0x2c,0x58,0xb0,0x7d,0xfa,0xe9,0xcf,0x83,0x1b,0x36,0x6c,
0xd8,0xad,0x47,0x8e,0x00
];
// Working buffers:
// data input and ecc append,image working buffer,fixed part of image,run lengths for badness
var strinbuf=[],eccbuf=[],qrframe=[],framask=[],rlens=[];
// Control values-width is based on version,last 4 are from table.
var version,width,neccblk1,neccblk2,datablkw,eccblkwid;
var ecclevel=2;
// set bit to indicate cell in qrframe is immutable. symmetric around diagonal
function setmask(x,y){
var bt;
if(x>y){bt=x;x=y;y=bt;}
bt=y;bt*= y;bt+=y;bt >>= 1;bt+=x;framask[bt]=1;
}
// enter alignment pattern-black to qrframe,white to mask(later black frame merged to mask)
function putalign(x,y){
var j;
qrframe[x+width* y]=1;
for (j = -2; j < 2; j++){
qrframe[x + j + width * (y - 2)] = 1;qrframe[x - 2 + width * (y + j + 1)] = 1;qrframe[x + 2 + width * (y + j)] = 1;qrframe[x + j + 1 + width * (y + 2)] = 1;
}
for(j=0;j<2;j++){
setmask(x-1,y+j);setmask(x+1,y-j);setmask(x-j,y-1);setmask(x+j,y+1);
}
}
//========================================================================
// Reed Solomon error correction
// exponentiation mod N
function modnn(x){
while(x >= 255){x -= 255;x=(x >> 8) +(x & 255);}
return x;
}
var genpoly=[];
// Calculate and append ECC data to data block. Block is in strinbuf,indexes to buffers given.
function appendrs(data,dlen,ecbuf,eclen){
var i,j,fb;
for(i=0;i<eclen;i++){strinbuf[ecbuf+i]=0;}
for(i=0;i<dlen;i++){
fb=glog[strinbuf[data+i] ^ strinbuf[ecbuf]];
if(fb != 255){
for(j=1;j<eclen;j++){strinbuf[ecbuf+j-1]=strinbuf[ecbuf+j] ^ gexp[modnn(fb+genpoly[eclen-j])];}
}else{
for(j=ecbuf;j<ecbuf+eclen;j++){strinbuf[j]=strinbuf[j+1];}
}
strinbuf[ecbuf+eclen-1]=fb == 255 ? 0 : gexp[modnn(fb+genpoly[0])];
}
}
//========================================================================
// Frame data insert following the path rules
// check mask-since symmetrical use half.
function ismasked(x,y){
var bt;
if(x>y){bt=x;x=y;y=bt;}
bt=y;bt+=y* y;bt >>= 1;bt+=x;
return framask[bt];
}
//========================================================================
// Apply the selected mask out of the 8.
function applymask(m){
var x,y,r3x,r3y;
switch(m){
case 0:
for(y=0;y<width;y++){
for(x=0;x<width;x++){
if(!(x+y & 1) && !ismasked(x,y)){qrframe[x+y* width] ^= 1;}
}
}
break;
case 1:
for(y=0;y<width;y++){
for(x=0;x<width;x++){
if(!(y & 1) && !ismasked(x,y)){qrframe[x+y* width] ^= 1;}
}
}
break;
case 2:
for(y=0;y<width;y++){
for(r3x=0,x=0;x<width;x++,r3x++){
if(r3x == 3){r3x=0;}
if(!r3x && !ismasked(x,y)){ qrframe[x+y* width] ^= 1;}
}
}
break;
case 3:
for(r3y=0,y=0;y<width;y++,r3y++){
if(r3y == 3){r3y=0;}
for(r3x=r3y,x=0;x<width;x++,r3x++){
if(r3x == 3){r3x=0;}
if(!r3x && !ismasked(x,y)){qrframe[x+y* width] ^= 1;}
}
}
break;
case 4:
for(y=0;y<width;y++){
for(r3x=0,r3y=y >> 1 & 1,x=0;x<width;x++,r3x++){
if(r3x == 3){r3x=0;r3y=!r3y;}
if(!r3y && !ismasked(x,y)){qrframe[x+y* width] ^= 1;}
}
}
break;
case 5:
for(r3y=0,y=0;y<width;y++,r3y++){
if(r3y == 3){r3y=0;}
for(r3x=0,x=0;x<width;x++,r3x++){
if(r3x == 3){r3x=0;}
if(!(x & y & 1)+!(!r3x | !r3y) && !ismasked(x,y)){qrframe[x+y* width] ^= 1;}
}
}
break;
case 6:
for(r3y=0,y=0;y<width;y++,r3y++){
if(r3y == 3){r3y=0;}
for(r3x=0,x=0;x<width;x++,r3x++){
if(r3x == 3){r3x=0;}
if(!((x & y & 1) +(r3x && r3x == r3y) & 1) && !ismasked(x,y)){qrframe[x+y* width] ^= 1;}
}
}
break;
case 7:
for(r3y=0,y=0;y<width;y++,r3y++){
if(r3y == 3){r3y=0;}
for(r3x=0,x=0;x<width;x++,r3x++){
if(r3x == 3){r3x=0;}
if(!((r3x && r3x == r3y) +(x+y & 1) & 1) && !ismasked(x,y)){qrframe[x+y* width] ^= 1;}
}
}
break;
}
return;
}
// Badness coefficients.
var N1=3,N2=3,N3=40,N4=10;
// Using the table of the length of each run,calculate the amount of bad image
//-long runs or those that look like finders;called twice,once each for X and Y
function badruns(length){
var i;
var runsbad=0;
for(i=0;i <= length;i++){if(rlens[i] >= 5){runsbad+=N1+rlens[i]-5;}}
// BwBBBwB as in finder
for(i=3;i<length-1;i+=2){
if(rlens[i-2] == rlens[i+2] && rlens[i+2] == rlens[i-1] && rlens[i-1] == rlens[i+1] && rlens[i-1]* 3 == rlens[i] &&(rlens[i-3] == 0 || i+3>length || rlens[i-3]* 3 >= rlens[i]* 4 || rlens[i+3]* 3 >= rlens[i]* 4)){runsbad+=N3;}
}
return runsbad;
}
// Calculate how bad the masked image is-blocks,imbalance,runs,or finders.
function badcheck(){
var x,y,h,b,b1;
var thisbad=0;
var bw=0;
// blocks of same color.
for(y=0;y<width-1;y++){
for(x=0;x<width-1;x++){
if(qrframe[x+width* y] && qrframe[x+1+width* y] && qrframe[x+width*(y+1)] && qrframe[x +1+width*(y+1)] || !(qrframe[x+width* y] || qrframe[x+1+width* y] || qrframe[x+width*(y+1)] || qrframe[x +1+width*(y+1)])){
thisbad+=N2;
}
}
}
// X runs
for(y=0;y<width;y++){
rlens[0]=0;
for(h=b=x=0;x<width;x++){
if((b1=qrframe[x+width* y]) == b){rlens[h]++;}
else {rlens[++h]=1;}
b=b1;bw+=b ? 1 : -1;
}
thisbad+=badruns(h);
}
// black/white imbalance
if(bw<0){bw=-bw;}
var big=bw;
var count=0;
big+=big << 2;
big <<= 1;
while(big>width* width){big -= width* width,count++;}
thisbad+=count* N4;
// Y runs
for(x=0;x<width;x++){
rlens[0]=0;
for(h=b=y=0;y<width;y++){
if((b1=qrframe[x+width* y]) == b){rlens[h]++;}
else {rlens[++h]=1;}
b=b1;
}
thisbad+=badruns(h);
}
return thisbad;
}
function genframe(instring){
var x,y,k,t,v,i,j,m;
// find the smallest version that fits the string
t=instring.length;
version=0;
do {
version++;
k=(ecclevel-1)* 4 +(version-1)* 16;
neccblk1=eccblocks[k++];
neccblk2=eccblocks[k++];
datablkw=eccblocks[k++];
eccblkwid=eccblocks[k];
k=datablkw*(neccblk1+neccblk2)+neccblk2-3 +(version <= 9);
if(t <= k){break;}
} while(version<40);
// FIXME-insure that it fits insted of being truncated
width=17+4* version;
// allocate,clear and setup data structures
v=datablkw +(datablkw+eccblkwid)*(neccblk1+neccblk2)+neccblk2;
for(t=0;t<v;t++){eccbuf[t]=0;}
strinbuf=instring.slice(0);
for(t=0;t<width* width;t++){qrframe[t]=0;}
for(t=0;t <(width*(width+1)+1)/2;t++){framask[t]=0;}
// insert finders-black to frame,white to mask
for(t=0;t<3;t++){
k=0;y=0;
if(t == 1){k=width-7;}
if(t == 2){y=width-7;}
qrframe[y+3+width*(k+3)]=1;
for(x=0;x<6;x++){
qrframe[y+x+width* k]=1;qrframe[y+width*(k+x+1)]=1;qrframe[y+6+width*(k+x)]=1;qrframe[y+x+1+width*(k+6)]=1;
}
for(x=1;x<5;x++){
setmask(y+x,k+1);setmask(y+1,k+x+1);setmask(y+5,k+x);setmask(y+x+1,k+5);
}
for(x=2;x<4;x++){
qrframe[y+x+width*(k+2)]=1;qrframe[y+2+width*(k+x+1)]=1;qrframe[y+4+width*(k+x)]=1;qrframe[y+x+1+width*(k+4)]=1;
}
}
// alignment blocks
if(version>1){
t=adelta[version];
y=width-7;
for(;;){
x=width-7;
while(x>t-3){
putalign(x,y);if(x<t){break;}x -= t;
}
if(y <= t+9){ break;}
y -= t;putalign(6,y);putalign(y,6);
}
}
// single black
qrframe[8+width*(width-8)]=1;
// timing gap-mask only
for(y=0;y<7;y++){
setmask(7,y);setmask(width-8,y);setmask(7,y+width-7);
}
for(x=0;x<8;x++){
setmask(x,7);setmask(x+width-8,7);setmask(x,width-8);
}
// reserve mask-format area
for(x=0;x<9;x++){setmask(x,8);}
for(x=0;x<8;x++){
setmask(x+width-8,8);
setmask(8,x);
}
for(y=0;y<7;y++){setmask(8,y+width-7);}
// timing row/col
for(x=0;x<width-14;x++){
if(x & 1){setmask(8+x,6);setmask(6,8+x);}
else{qrframe[8+x+width* 6]=1;qrframe[6+width*(8+x)]=1;}
}
// version block
if(version>6){
t=vpat[version-7];k=17;
for(x=0;x<6;x++){
for(y=0;y<3;y++,k--){
if(1 &(k>11 ? version >> k-12 : t >> k)){
qrframe[5-x+width*(2-y+width-11)]=1;qrframe[2-y+width-11+width*(5-x)]=1;
}else{
setmask(5-x,2-y+width-11);setmask(2-y+width-11,5-x);
}
}
}
}
// sync mask bits-only set above for white spaces,so add in black bits
for(y=0;y<width;y++){for(x=0;x <= y;x++){if(qrframe[x+width* y]){setmask(x,y);}}}
// convert string to bitstream
// 8 bit data to QR-coded 8 bit data(numeric or alphanum,or kanji not supported)
v=strinbuf.length;
// string to array
for(i=0;i<v;i++){ eccbuf[i]=strinbuf.charCodeAt(i);}
strinbuf=eccbuf.slice(0);
// calculate max string length
x=datablkw*(neccblk1+neccblk2)+neccblk2;
if(v >= x-2){v=x-2;if(version>9){ v--;}}
// shift and repack to insert length prefix
i=v;
if(version>9){
strinbuf[i+2]=0;strinbuf[i+3]=0;
while(i--){t=strinbuf[i];strinbuf[i+3] |= 255 & t << 4;strinbuf[i+2]=t >> 4;}
strinbuf[2] |= 255 & v << 4;strinbuf[1]=v >> 4;strinbuf[0]=0x40 | v >> 12;
}else{
strinbuf[i+1]=0;strinbuf[i+2]=0;
while(i--){t=strinbuf[i];strinbuf[i+2] |= 255 & t << 4;strinbuf[i+1]=t >> 4;}
strinbuf[1] |= 255 & v << 4;strinbuf[0]=0x40 | v >> 4;
}
// fill to end with pad pattern
i=v+3 -(version<10);
while(i<x){
strinbuf[i++]=0xec;
// buffer has room if(i == x) break;
strinbuf[i++]=0x11;
}
// calculate and append ECC
// calculate generator polynomial
genpoly[0]=1;
for(i=0;i<eccblkwid;i++){
genpoly[i+1]=1;
for(j=i;j>0;j--){ genpoly[j]=genpoly[j] ? genpoly[j-1] ^ gexp[modnn(glog[genpoly[j]]+i)] : genpoly[j-1];}
genpoly[0]=gexp[modnn(glog[genpoly[0]]+i)];
}
for(i=0;i <= eccblkwid;i++){genpoly[i]=glog[genpoly[i]];}// use logs for genpoly[] to save calc step
// append ecc to data buffer
k=x;y=0;
for(i=0;i<neccblk1;i++){appendrs(y,datablkw,k,eccblkwid);y+=datablkw;k+=eccblkwid;}
for(i=0;i<neccblk2;i++){appendrs(y,datablkw+1,k,eccblkwid);y+=datablkw+1;k+=eccblkwid;}
// interleave blocks
y=0;
for(i=0;i<datablkw;i++){
for(j=0;j<neccblk1;j++){eccbuf[y++]=strinbuf[i+j* datablkw];}
for(j=0;j<neccblk2;j++){eccbuf[y++]=strinbuf[neccblk1* datablkw+i+j*(datablkw+1)];}
}
for(j=0;j<neccblk2;j++){eccbuf[y++]=strinbuf[neccblk1* datablkw+i+j*(datablkw+1)];}
for(i=0;i<eccblkwid;i++){
for(j=0;j<neccblk1+neccblk2;j++){ eccbuf[y++]=strinbuf[x+i+j* eccblkwid];}
}
strinbuf=eccbuf;
// pack bits into frame avoiding masked area.
x=y=width-1;
k=v=1;// up,minus
/* inteleaved data and ecc codes*/
m=(datablkw+eccblkwid)*(neccblk1+neccblk2)+neccblk2;
for(i=0;i<m;i++){
t=strinbuf[i];
for(j=0;j<8;j++,t <<= 1){
if(0x80 & t){qrframe[x+width* y]=1;}
do {
// find next fill position
if(v){x--;}
else {
x++;
if(k){if(y != 0){y--;}else {x -= 2;k=!k;if(x == 6){x--;y=9;}}}
else{if(y != width-1){ y++;}else {x -= 2;k=!k;if(x == 6){x--;y -= 8;}}}
}
v=!v;
} while(ismasked(x,y));
}
}
// save pre-mask copy of frame
strinbuf=qrframe.slice(0);
t=0;// best
y=30000;// demerit
// for instead of while since in original arduino code
// if an early mask was "good enough" it wouldn't try for a better one
// since they get more complex and take longer.
for(k=0;k<8;k++){
applymask(k);// returns black-white imbalance
x=badcheck();
if(x<y){// current mask better than previous best?
y=x;t=k;
}
if(t == 7){break;}// don't increment i to a void redoing mask
qrframe=strinbuf.slice(0);// reset for next pass
}
if(t != k){ // redo best mask-none good enough,last wasn't t
applymask(t);
}
// add in final mask/ecclevel bytes
y=fmtword[t +(ecclevel-1 << 3)];
// low byte
for(k=0;k<8;k++,y >>= 1){
if(y & 1){qrframe[width-1-k+width* 8]=1;if(k<6){qrframe[8+width* k]=1;}else {qrframe[8+width*(k+1)]=1;}}
}
// high byte
for(k=0;k<7;k++,y >>= 1){
if(y & 1){qrframe[8+width*(width-7+k)]=1;if(k){qrframe[6-k+width* 8]=1;}else {qrframe[7+width* 8]=1;}}
}
return qrframe;
}
var api={
get ecclevel(){return ecclevel;},
set ecclevel(val){ecclevel=val;},
get size(){return _size;},
set size(val){_size=val;},
getFrame: function(string){return genframe(string);},
//这里的utf16to8(str)是对Text中的字符串进行转码,让其支持中文
utf16to8: function(str){
var out,i,len,c;
out="";len=str.length;
for(i=0;i<len;i++){
c=str.charCodeAt(i);
if(c >= 0x0001 && c <= 0x007F){
out+=str.charAt(i);
}else if(c>0x07FF){
out+=String.fromCharCode(0xE0 | c >> 12 & 0x0F);out+=String.fromCharCode(0x80 | c >> 6 & 0x3F);out+=String.fromCharCode(0x80 | c >> 0 & 0x3F);
}else{
out+=String.fromCharCode(0xC0 | c >> 6 & 0x1F);out+=String.fromCharCode(0x80 | c >> 0 & 0x3F);
}
}
return out;
},
/*新增$this参数,传入组件的this,兼容在组件中生成*/
drawQrcode: function(str,cavW,cavH,$this,ecc){
var that=this;
ecclevel=ecc || ecclevel;
var size=Math.min(cavW,cavH);
str=that.utf16to8(str);//增加中文显示
var frame=that.getFrame(str),
px=Math.round(size /(width+8));
var roundedSize=px*(width+8),offset=Math.floor((size-roundedSize)/2);
size=roundedSize;
var ctx='';
for(var i=0;i<width;i++){
if(i!=0){ctx+='\n';}
for(var j=0;j<width;j++){
if(frame[j* width+i]){ctx+=' ';}
else{
ctx+='■';
}//■●◆★■▲
}
}
ctx+='';
return ctx;
}
};
module.exports={api};
}();
收起阅读 »