使用JavaScript创建SVG矢量图Code128编码_code 128矢量-程序员宅基地

技术标签: Code128  WEB  SVG  javascript  

起因

本来设计使用20开头的EAN13 作为店内码的, 实际查询发现. 一些20开头的也是商品条码. 这就有点尴尬了, 为了不和商品条码冲突, 只好改变编码规则, 因此需要实现输出SVG格式的Code128条码.

设计

Code128是支持ABC混合编码的, 在生成条码过程中可以切换码表. 考虑字符密度,优先使用 Code128-C 作为数字编码, 如果有字母,则切换到Code128-B.

这里附上 Code-128码表

ID Code128A Code128B Code128C BandCode 编码值
0 SP SP 0 212222 bbsbbssbbss
1 ! ! 1 222122 bbssbbsbbss
2 " " 2 222221 bbssbbssbbs
3 # # 3 121223 bssbssbbsss
4 $ $ 4 121322 bssbsssbbss
5 % % 5 131222 bsssbssbbss
6 & & 6 122213 bssbbssbsss
7 7 122312 bssbbsssbss
8 ( ( 8 132212 bsssbbssbss
9 ) ) 9 221213 bbssbssbsss
10 * * 10 221312 bbssbsssbss
11 + + 11 231212 bbsssbssbss
12 , , 12 112232 bsbbssbbbss
13 - - 13 122132 bssbbsbbbss
14 . . 14 122231 bssbbssbbbs
15 / / 15 113222 bsbbbssbbss
16 0 0 16 123122 bssbbbsbbss
17 1 1 17 123221 bssbbbssbbs
18 2 2 18 223211 bbssbbbssbs
19 3 3 19 221132 bbssbsbbbss
20 4 4 20 221231 bbssbssbbbs
21 5 5 21 213212 bbsbbbssbss
22 6 6 22 223112 bbssbbbsbss
23 7 7 23 312131 bbbsbbsbbbs
24 8 8 24 311222 bbbsbssbbss
25 9 9 25 321122 bbbssbsbbss
26 : : 26 321221 bbbssbssbbs
27 ; ; 27 312212 bbbsbbssbss
28 < < 28 322112 bbbssbbsbss
29 = = 29 322211 bbbssbbssbs
30 > > 30 212123 bbsbbsbbsss
31 ? ? 31 212321 bbsbbsssbbs
32 @ @ 32 232121 bbsssbbsbbs
33 A A 33 111323 bsbsssbbsss
34 B B 34 131123 bsssbsbbsss
35 C C 35 131321 bsssbsssbbs
36 D D 36 112313 bsbbsssbsss
37 E E 37 132113 bsssbbsbsss
38 F F 38 132311 bsssbbsssbs
39 G G 39 211313 bbsbsssbsss
40 H H 40 231113 bbsssbsbsss
41 I I 41 231311 bbsssbsssbs
42 J J 42 112133 bsbbsbbbsss
43 K K 43 112331 bsbbsssbbbs
44 L L 44 132131 bsssbbsbbbs
45 M M 45 113123 bsbbbsbbsss
46 N N 46 113321 bsbbbsssbbs
47 O O 47 133121 bsssbbbsbbs
48 P P 48 313121 bbbsbbbsbbs
49 Q Q 49 211331 bbsbsssbbbs
50 R R 50 231131 bbsssbsbbbs
51 S S 51 213113 bbsbbbsbsss
52 T T 52 213311 bbsbbbsssbs
53 U U 53 213131 bbsbbbsbbbs
54 V V 54 311123 bbbsbsbbsss
55 W W 55 311321 bbbsbsssbbs
56 X X 56 331121 bbbsssbsbbs
57 Y Y 57 312113 bbbsbbsbsss
58 Z Z 58 312311 bbbsbbsssbs
59 [ [ 59 332111 bbbsssbbsbs
60 \ \ 60 314111 bbbsbbbbsbs
61 ] ] 61 221411 bbssbssssbs
62 ^ ^ 62 431111 bbbbsssbsbs
63 _ _ 63 111224 bsbssbbssss
64 NUL ` 64 111422 bsbssssbbss
65 SOH a 65 121124 bssbsbbssss
66 STX b 66 121421 bssbssssbbs
67 ETX c 67 141122 bssssbsbbss
68 EOT d 68 141221 bssssbssbbs
69 ENQ e 69 112214 bsbbssbssss
70 ACK f 70 112412 bsbbssssbss
71 BEL g 71 122114 bssbbsbssss
72 BS h 72 122411 bssbbssssbs
73 HT i 73 142112 bssssbbsbss
74 LF j 74 142211 bssssbbssbs
75 VT k 75 241211 bbssssbssbs
76 FF I 76 221114 bbssbsbssss
77 CR m 77 413111 bbbbsbbbsbs
78 SO n 78 241112 bbssssbsbss
79 SI o 79 134111 bsssbbbbsbs
80 DLE p 80 111242 bsbssbbbbss
81 DC1 q 81 121142 bssbsbbbbss
82 DC2 r 82 121241 bssbssbbbbs
83 DC3 s 83 114212 bsbbbbssbss
84 DC4 t 84 124112 bssbbbbsbss
85 NAK u 85 124211 bssbbbbssbs
86 SYN v 86 411212 bbbbsbssbss
87 ETB w 87 421112 bbbbssbsbss
88 CAN x 88 421211 bbbbssbssbs
89 EM y 89 212141 bbsbbsbbbbs
90 SUB z 90 214121 bbsbbbbsbbs
91 ESC { 91 412121 bbbbsbbsbbs
92 FS | 92 111143 bsbsbbbbsss
93 GS } 93 111341 bsbsssbbbbs
94 RS ~ 94 131141 bsssbsbbbbs
95 US DEL 95 114113 bsbbbbsbsss
96 FNC3 FNC3 96 114311 bsbbbbsssbs
97 FNC2 FNC2 97 411113 bbbbsbsbsss
98 SHIFT SHIFT 98 411311 bbbbsbsssbs
99 CODEC CODEC 99 113141 bsbbbsbbbbs
100 CODEB FNC4 CODEB 114131 bsbbbbsbbbs
101 FNC4 CODEA CODEA 311141 bbbsbsbbbbs
102 FNC1 FNC1 FNC1 411131 bbbbsbsbbbs
103 StartA StartA StartA 211412 bbsbssssbss
104 StartB StartB StartB 211214 bbsbssbssss
105 StartC StartC StartC 211232 bbsbssbbbss
106 Stop Stop Stop 2331112 bbsssbbbsbsbb

编码构成

开始位 + 后面所有的数据按顺序拼接 + 校验位 + 结束位

编码索引的103-106为起始位于结束位,只会在开头或结尾出现

我们首先使用一个简单的例子来解释如何使用三种编码方式进行条形码的编码:

需要编码成条形码的数据:1346

对于Code128A编码:

位类型 码表 线 校验值
起始位 StartA bbsbssssbss 103
数据位 Code128A中的1 bssbbbssbbs 103 + 17 * 1
数据位 Code128A中的3 bbssbsbbbss 103 + 19 * 2
数据位 Code128A中的4 bbssbssbbbs 103 + 20 * 3
数据位 Code128A中的6 bbssbbbsbss 103 + 22 * 4
校验位 校验值 % 103 ---- 前面的求和 % 103后查表.
停止位 Stop bbsssbbbsbsbb

对于Code128B编码:

位类型 码表 线 校验值
起始位 StartB bbsbssssbss 104
数据位 Code128B中的1 bssbbbssbbs 17 * 1
数据位 Code128B中的3 bbssbsbbbss 19 * 2
数据位 Code128B中的4 bbssbssbbbs 20 * 3
数据位 Code128B中的6 bbssbbbsbss 22 * 4
校验位 校验值 % 103 ---- 前面的求和 % 103后查表.
停止位 Stop bbsssbbbsbsbb

对于Code128C编码:

Code128C编码时,只能编码数字内容,并且在编码前会将偶数个的数字两个两个分为一组,进行编码:

位类型 码表 线 校验值
起始位 StartC bbsbssbbbss 105
数据位 Code128C中的13 bssbbsbbbss 13 * 1
数据位 Code128C中的46 bsbbbsssbbs 46 * 2
校验位 校验值 % 103 ---- 前面的求和 % 103 后查表
停止位 Stop bbsssbbbsbsbb

混合编码

中间要切换编码只需加入切换编码查表线值表即可,索引需要计入校验,计算方法一致。

实现代码

const codeC = [
    1740,1644,1638,1176,1164,1100,1224,1220,1124,1608,1604,1572,1436,1244,1230,1484,1260,1254,1650,1628,
    1614,1764,1652,1902,1868,1836,1830,1892,1844,1842,1752,1734,1590,1304,1112,1094,1416,1128,1122,1672,
    1576,1570,1464,1422,1134,1496,1478,1142,1910,1678,1582,1768,1762,1774,1880,1862,1814,1896,1890,1818,
    1914,1602,1930,1328,1292,1200,1158,1068,1062,1424,1412,1232,1218,1076,1074,1554,1616,1978,1556,1146,
    1340,1212,1182,1508,1268,1266,1956,1940,1938,1758,1782,1974,1400,1310,1118,1512,1506,1960,1954,1502,
    1518,1886,1966,1668,1680,1692,6379
],codeB=[
    null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,
    null,null,null,null,null,null,null,null,null,null,null,null,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,
    18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,76,42,43,44,45,46,47,48,49,50,51,52,
    53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,null,77,78,79,80,81,82,83,84,85,86,87,
    88,89,90,91,92,93,94,95,102,97,96,100
];

function Code128B(code, conf){
    
    let chars = code.split(/(\d{2}|[^\d]{1})/).filter(v=>v!=''), sum = 105, n=[], bits = [], pos = 1;
    var enc;
    const modeB=0,modeC=1;
    chars.forEach((ch, i)=>{
    
        let len = ch.length, v;
        if(i == 0){
    
            if(len == 1){
    
                sum = 104;
                enc = modeB; 
                v = codeB[ch.charCodeAt(0)];
                n.push(codeC[104]);
            }else{
    
                sum = 105;
                enc = modeC;
                v = parseInt(ch);
                n.push(codeC[105]);
                //console.log('start C', ch, v);
            }
            n.push(codeC[v]);
        }else{
    
            if(enc == modeC){
    
                if(len == 1){
    
                    enc = modeB;
                    sum += 100 * pos++;
                    n.push(codeC[100]);
                    v = codeB[ch.charCodeAt(0)];
                }else{
    
                    v = parseInt(ch);
                }
            }else{
    
                if(len == 1){
    
                    v = codeB[ch.charCodeAt(0)];
                }else{
    
                    enc = modeC;
                    sum += 99 * pos++;
                    n.push(codeC[99]); //codeB => codeC
                    v = parseInt(ch);
                }
            }
            n.push(codeC[v]);
        }
        sum += v * pos++;
    });

    n.push(codeC[sum % 103], 6379);
    n.forEach(v=>{
    
        var b = []
        do{
    
            b.push(v & 1 ? 1:0);
            v >>=1;
        }while(v > 0)
        bits.push(...b.reverse());
    })
    //console.log(bits);
    var x=-1, w = 0, nCount = bits.length+6, y = conf.name ? (2+conf.fsize) : 0,s = [],
    bar = [`<svg viewBox="0 0 ${
      nCount} ${
      conf.h}" width="100%" height="100%" xmlns="http://www.w3.org/2000/svg" xmlns:xlink= "http://www.w3.org/1999/xlink">`];

    bits.forEach((v,i)=>{
    
        if(0 == v || i == bits.length-1){
    
            if(w > 0){
    
                var h = (x < 14 || x > bits.length - 12)? conf.h - y : conf.h - y - 6.5;
                s.push('M', x, ' ', y,'h', w, 'v', h, 'h', -w, 'Z')
                x = -1;w = 0;
            }
        }else{
    
            if(-1 == x ){
    x = i+3;}
            w++;
        }
    })

    bar.push('<path d="', s.join(''),'"/>')
    const unit = (nCount - (6 + 13 + 14)) / code.length;
    for(var i = 0; i < code.length;i ++){
    
        bar.push('<text x="', 16 + i * unit ,'" y="', conf.h - 0.4,'" text-anchor="left" font-size="7" font-family="Verdana">', code[i] , '</text>')
    }
    if(conf.name){
    
        bar.push('<text x="',nCount/2,'" y="',conf.fsize - 0.5,'" font-size="',conf.fsize,'" width="',nCount,'" text-anchor="middle" font-family="Verdana">',conf.name,'</text>')
    }
    bar.push('</svg>')
    return {
    
        svg: bar.join(''),
        lines: nCount
    }
}

var svg = Code128B('Z65432189120', {
    h:45, name:'很好', fsize:9});

上面的代码执行效果如下:

Z 6 5 4 3 2 1 8 9 1 2 0 很好
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/bywayboy/article/details/124411669

智能推荐

【无标题】App iOS端适配iOS 15系统_lsapplicationqueriesschemes 超过 50 怎么办-程序员宅基地

文章浏览阅读2.6k次。各位好:App iOS端适配iOS 15系统,适配后将使用新的xcode 13打包提交App Store。一、适配内容:1、新增了iPhone 13 mini机型(尺寸同iPhone12 mini),5.4 英寸 (对角线) OLED 全面屏,屏幕分辨率为2340 x 1080 像素。如果是通过分辨率来判断则需要增加一个模式。 #define iPhone13mini ([UIScreen instancesRespondToSelector:@selector(currentMo_lsapplicationqueriesschemes 超过 50 怎么办

抓包工具Fiddler的下载安装使用_fiddler抓包下载-程序员宅基地

文章浏览阅读497次。右侧显示就是我们主机发送http/https请求的记录。如果我们要查看某一次访问,可以双击该记录,在右侧就会显示这次http请求的内容以及返回的响应的内容。右键全选,点击remove,选择selected sessions,就能删除选择的sessions。安装过程只用一路next即可;_fiddler抓包下载

html语言ppt,htmlppt课件-程序员宅基地

文章浏览阅读642次。PPT内容这是htmlppt课件,关于第2章Web编程技术,包括了HTML的发展历史,HTML的基本框架,HTML的各种常用标记:文字标记、图片标记、超级链接标记,CSS的基本使用方法,如何让CSS与HTML协同工作,JavaScript中的变量、数组、表达式、运算符、流程控制语句,JavaScript的函数、内置对象、浏览器对象的层次和DOM模型的建立和使用等内容,欢迎点击下载。第2章 Web编..._html if elseppt课件

solr html显示,Solr查询界面-程序员宅基地

文章浏览阅读259次。您可以使用查询界面将搜索查询提交给 Solr 集合并分析结果。在下面截图中的例子中,查询已经被提交,并且界面显示了作为 JSON 形式发送到浏览器的查询结果。在这个例子中,genre:Fantasy 的查询被发送到 “films” 集合。表单中的所有其他选项都使用了默认值,下表中对此进行了简要介绍,本指南的后面部分将对此进行详细介绍。该响应显示在窗体的右侧。对 Solr 的请求只是简单的 HTTP..._solr查询界面

【Java EE】Spring请求如何传递参数详解-程序员宅基地

文章浏览阅读1.5k次,点赞65次,收藏51次。Spring请求如何传递参数详解,传递单个参数,传递多个参数,传递对象,后端参数重命名(后端参数映射),传递数组,传递集合,传递JSON数据,获取URL中参数@PathVariable,上传文件@RequestPart,获取Cooki/Session,获取Header

串口通讯参考文章

Android 串口开发,发送串口命令,读卡,反扫码,USB通讯,实现demo。——持续更新_androidschedulers.from(mwritethread.getlooper());-CSDN博客

随便推点

Mendix Excel导出介绍_mendix实现excel导出-程序员宅基地

文章浏览阅读320次。本文介绍了Excel导出的两种方式及成果展示_mendix实现excel导出

5 gtm 工作原理_基于GTM法的水泥稳定碎石力学性能研究-程序员宅基地

文章浏览阅读226次。文章来源:微信公众号”沥青路面“引 言众所周知,以水泥稳定碎石为代表的半刚性材料是中国目前使用最为广泛的基层材料,因为其力学性能优良、使用成本较低、原材料来源广泛和施工工艺简单等优点,水泥稳定碎石在未来十几年内仍将是中国使用最为广泛的基层材料。目前水泥稳定碎石在设计和施工方面存在一些问题,例如室内成型方式与实际道路受力状态存在一定差异;设计指标和施工检测指标相关性不足;对矿质石料级配的要求没有体现..._无侧限抗压强度与劈裂强度的的关系

黑科技,Python 脚本帮你找出微信上删除你好友的人_微信出现brandsessionholder-程序员宅基地

文章浏览阅读1.5k次。编者按:本文来自稀土掘金江昪编译自 Github:0x5e/wechat-deleted-friends “ 清理下[微笑],不用回。你的朋友圈没事也该清清了,打开设置,通用,功能,群助手,全选,把我的信息粘贴一下,就可以了,发送就知道谁把你删了,方便你清人,不清不知道 ,一清吓一跳。” 相信大家在微信上一定被上面的这段话刷过屏,群发消息应该算是微信上流传最广的找到删除好友的方法..._微信出现brandsessionholder

MySQL存储过程 游标循环的使用_存储过程 重复定义同名游标 会覆盖吗?-程序员宅基地

文章浏览阅读1.5k次。MySQL存储过程 游标循环的使用_存储过程 重复定义同名游标 会覆盖吗?

浙江大学计算机科学导论试题,2003年度浙江大学计算机科学导论试卷.doc-程序员宅基地

文章浏览阅读372次。浙江大学2003-2004学年第一学期期末考试<>课程试卷A姓名: 专业: 学号:单选题(每小题1分,共20分)1.若计算机内存中有若干个内存单元,它们的地址编号从00H到FFH,则这些内存单元总共可存放的数据数量为:( B )A.256 bitB.256 ByteC.255 KBD.255 Kb2. 计算机网络的最基本功能就是在网络中的计算机之..._浙江大学计算机科学导论连线题

汽车信息安全入门总结(1)

汽车信息安全从2015年开始被引起重视发展至今已近10年时间,虽然有很多高屋建瓴的白皮书、指导标准可以指导我们从宏观了解汽车信息安全这个新兴行业,但真正实际需求落实到我们一线开发人员身上,总归感觉缺少点最底层的逻辑闭环。与汽车传统的主被动功能安全相比,汽车信息安全问题一旦出现可能会带来巨大影响,不仅对驾驶员、乘客的人身安全、隐私安全和财产安全造成影响,还会给车企或者供应商带来巨大经济损失,更有甚者影响国家安全(参考Tesla)。任何事物的出现都背景和根源,汽车信息安全也不例外。今天就来聊聊个人粗浅的看法。

推荐文章

热门文章

相关标签