这篇文章是我发表在极客基地的原创,现在我把它搬回我自己的博客。
事出有因:前段时间一个土豪朋友说问我,嘿给我做个360表盘呗。我说这么高大上还可以制作。然后我就去恶补,知道了facer,知道了facer的文件face,知道了这其实是个压缩文件,知道了他的构成结构。但是当我去找制作教程的时候,竟然没有搜到!找到的只是别人做好的。难道大家都自己悄悄研究去做好卖钱了么。哈开个玩笑。后来微博发了个说过两天出个制作教程。好想现在过来好几天了,得兑现了。由于我没有360手表做全面的测试,也不好意思老麻烦土豪朋友去测试。所有下面教程可能有些错误,请大家跟我一起改进。
教程开始:
一.工具准备:1.Photoshop(或其他做图软件代替,必须因为没图表盘的花样就少很多)
2.Notepad++(Linux 推荐sublime或者vim,考虑到要作图,我选用win下notepad++)
3.解压缩软件WinRar,7Z等。
二.表盘文件结构如下:
每一个表盘文件后缀名是.face,也有zip的不做解释一样的东西。.face文件实际上是个zip压缩文件,你在linux中file .face 就会显示zip archive
所有将face文件重命名为.zip 就可以用解压缩文件解压,当然你可以用7z邮件.face文件直接解压。解压后的目录里面通常包含四个文件:
img 文件夹;description.json文件;preview.png文件,watchface.json文件
各文件解释:
1.img文件夹:这里保存着表盘用的到所有图片资源,表针,表盘背景等等。
2.description.json:这是一个json文件(什么事json不做解释,也有xml的),这个文件对表盘的描述文件有表盘名称啊,ID,版本号什么的。这里不做过多解释后面会讲到。
3.preview.png:表盘预览文件,你在facer中倒入制作好的表盘的时候就会看到这张图片。
4.watchface.json:这个文件是最主要的,没这个文件你的图片img文件夹就是废的,你的手表也不会有时间显示。那这个文件到底是干嘛的?这个文件定义表盘的所有样式,时间显示,日期显示。天气显示等等。通过key-value(键值)的方式对img文件夹中的资源操作,进行布局调整和设置。这个文件后面会花大篇幅去讲。
ps:有些表盘文件解压还有fonts文件夹定义个性化字体的。
下面我以一个表盘为例开始讲解每个文件的细节分析文件中的每个语句,我从网上随便下了一个表盘。叫做luxurious-star-of-david-14a08b1cf0f.face
第一步:深入了解img文件夹
img 文件夹为图片文件夹,打开的目录是没有后缀名的,但其实是png格式。并且文件名都以hash值命名。如下
我们将图片文件重命名添加后缀.png就可以看到真面目了:
看这就是全貌了,有表盘背景(最后一张),还有表针。
第二步:preview.png文件了解
preview.png是预览文件也是整个表盘的最终显示效果。当你把face文件导入你的手机中用facer打开的时候你就会看到这张图片。下面放出preview.png的图大家对照img的文件详情就知道做出一一对应了。
这下大家就明白了。img中那四个闪闪发光的“大钻石”就是表盘外围的样子,还有三个表针,加一个背景图片。
第三步:结合上面img文件夹和preview.png的解释展开我们的大片! watchface.json文件详解
当我们解压后打开watchface.json文件的时候会显示这样,前提你把notepad++的自动换行打开,view—–word warp,不然你只能看到一行,这一行会很长很长。就不上图了。下面开自动换行打开的效果:
当你看到这个的时候或许会说一句:WTF 亲,稍安勿燥。让我们来揭开它神秘的面纱。你会发现json这个基本格式是:
[{},{},{}……] []表示一个数组 {}表示一个描述对象
那我们就以大括号对文件进行换行处理来梳理下(notepad++ 的括号匹配高亮一会就弄好的)。整理好总共分为31行,如下图:
这样是不是好看多了,不那么恐惧了,每行为一个元素的描述。图片文字等等。下面我将分为三大块来讲解这个文件,文件原文会在后面提供下载:
①从1~14行
{“id”:0,”is_tinted”:false,”alignment”:0,”height”:”335”,”hash”:”fdedd33031df0b75d2aa52c1d6351a4f”,”r”:”0”,”width”:”376”,”opacity”:”100”,”tint_color”:0,”type”:”image”,”y”:”-10”,”low_power”:true,”x”:”-30”}
先看这行:挨着参数解释 (讲之前明确一点:360表盘默认图片大小320*320像素)
id:0 一般背景图片id都为0,然后时针,分针等id依此增加。
is_tinted:这个参数我拿捏不准什么效果,但是这个参数仅在type:image的语句中出现并且都是false值。翻了好多别人做好的,都是酱紫。
alignment:这个值字面上对准,在这里0就是top left alignment(左上角对准对齐),一会放个图你就知道了
hash:图片文件的名称
r:不多说旋转角度
height:图片的高度 width:图片宽度这段吧 宽设为376,高设为335,但是你打开附近后解压得到的是540480,这里他会自动缩放这张图片为376335
opactiy:100%不透明
tint_color:着色颜色:跟is_tinted 也是图片文件有的参数看了下都是0,等我下次遇到其他值我就知道这家伙了:lol
type:image你所操作的对象类型,显然我们这是一个图片,因为只有图片才有hash参数。
y:-10 x=-30 图片相对于320*320图片也就是默认表盘大小的左上角分别偏移10个30个像素;没听明白看下图
上图中两个图层白色图层为320320,当我把376335拖进来与前面的top left对齐的时候,会看到这张图片纹理明显的不对称居中了,这时候我们x offset,y offset把他偏移过去,就居中,这下就懂了。
low_power:true 就是电量低的时候这张图片仍然显示,不显示就是false咯
(这行终于解释完了!!!………………)
{“width”:”40”,”type”:”shape”,”id”:1,”stroke_size”:”1”,”height”:”40”,”r”:”60”,”color”:”-1”,”shape_opt”:1,”opacity”:”100”,”radius”:”20”,”shape_type”:0,”y”:”155”,”x”:”210”,”low_power”:true,”sides”:”6”},
{“width”:”40”,”type”:”shape”,”id”:2,”stroke_size”:”2”,”height”:”40”,”r”:”60”,”color”:”-65536”,”shape_opt”:1,”opacity”:”100”,”radius”:”18”,”shape_type”:0,”y”:”155”,”x”:”210”,”low_power”:true,”sides”:”6”},
这两行干了个啥?就是画了一个白色和一个红色的圆看下面解释
width height都为40 ,这个其实就是PS中新建一个背景透明的画布,去补习下PS就知道嘿嘿。然后这个画布位置在哪里呢,y:155 X:210 这个值怎么找
PS 标尺打开x,y多少你拉多少就出来了。x,y 本质都是offset,都是相对于左上角。画布位置找到了,要画什么呢? 你看人慢慢描述要画什么。
type: shape 我要画的类型是个形状。id:1嗯给个id,stroke_size :笔触大小,就是粗细啦啦。r:rotation 60,颜色color:-1 就是白色了。shape_opt:有两个值1和0 ,1为不填充,0为填充,所有你看到上面preview.png中那两个白色和红色的圈都是空心。opacity前面已经介绍过不做解释。radius就是半径:20像素.刚好充满前面的画布有木有。shape_type:就是形状类型。 0 是圆。后面还会介绍其他参数。sides:其实是几边形。(好的这两句解释完毕)
{“width”:”40”,”type”:”shape”,”id”:3,”stroke_size”:”1”,”height”:”40”,”color”:”-65536”,”r”:”60”,”shape_opt”:1,”opacity”:”100”,”radius”:”18”,”shape_type”:4,”y”:”155”,”sides”:”6”,”low_power”:true,”x”:”210”},
{“width”:”40”,”type”:”shape”,”id”:4,”stroke_size”:”1”,”height”:”40”,”color”:”-65536”,”r”:”0”,”shape_opt”:1,”opacity”:”100”,”radius”:”18”,”shape_type”:4,”y”:”155”,”sides”:”6”,”low_power”:true,”x”:”210”},
这两句跟上面基本一样。就是颜色变为了红色:-65536 半径变为18 shape_type:4 这是三角形 红色三角形。一个不旋转一个旋转60度,大家看preview.png就可以知道了。
{“width”:”40”,”type”:”shape”,”id”:5,”stroke_size”:”5”,”height”:”40”,”color”:”-1”,”r”:”0”,”shape_opt”:0,”opacity”:”100”,”radius”:”10”,”shape_type”:2,”y”:”162”,”sides”:”8”,”low_power”:true,”x”:”300”},
{“width”:”40”,”type”:”shape”,”id”:6,”stroke_size”:”5”,”height”:”40”,”color”:”-1”,”r”:”0”,”shape_opt”:0,”opacity”:”100”,”radius”:”10”,”shape_type”:2,”y”:”302”,”sides”:”8”,”low_power”:true,”x”:”155”},
{“width”:”40”,”type”:”shape”,”id”:7,”stroke_size”:”5”,”height”:”40”,”color”:”-1”,”r”:”0”,”shape_opt”:0,”opacity”:”100”,”radius”:”10”,”shape_type”:2,”y”:”16”,”sides”:”8”,”low_power”:true,”x”:”160”},
{“width”:”40”,”type”:”shape”,”id”:8,”stroke_size”:”5”,”height”:”40”,”color”:”-1”,”r”:”0”,”shape_opt”:0,”opacity”:”100”,”radius”:”10”,”shape_type”:2,”y”:”162”,”sides”:”8”,”low_power”:true,”x”:”15”},
这四句跟前面一样,大概解释一下:看到没x,y都不一样,你用标尺拉一下就会看到是preview.PNG 中的四个“钻石的顶部”如下图.然后再这个位置画半径为10,shape_type:2多边形。 sides:8 就是8边形。颜色都为color:-1 白色,shape_opt:0 填充。好解释完毕
{“alignment”:0,”is_tinted”:false,”hash”:”b3cb8fdbe0c91f6849937e46ee70e4f5”,”width”:”18”,”type”:”image”,”id”:7,”stroke_size”:”5”,”height”:”15”,”color”:”-1”,”r”:”50”,”shape_opt”:0,”opacity”:”100”,”radius”:”10”,”tint_color”:0,”shape_type”:2,”y”:”290”,”sides”:”8”,”x”:”155”,”low_power”:true},
{“id”:5,”alignment”:0,”is_tinted”:false,”height”:”15”,”r”:”50”,”hash”:”b3cb8fdbe0c91f6849937e46ee70e4f5”,”width”:”18”,”opacity”:”100”,”tint_color”:0,”type”:”image”,”y”:”290”,”x”:”155”,”low_power”:true},
{“id”:5,”alignment”:0,”is_tinted”:false,”height”:”15”,”r”:”50”,”hash”:”1351e21aea8fc7867c633e3cd941ae8c”,”width”:”18”,”opacity”:”100”,”tint_color”:0,”type”:”image”,”y”:”5”,”x”:”160”,”low_power”:true},
{“id”:6,”alignment”:0,”is_tinted”:false,”height”:”15”,”r”:”50”,”hash”:”6df35b8567c9b950631363ec7fc6f9c9”,”width”:”18”,”opacity”:”100”,”tint_color”:0,”type”:”image”,”y”:”150”,”x”:”300”,”low_power”:true},
{“id”:7,”alignment”:0,”is_tinted”:false,”height”:”15”,”r”:”50”,”hash”:”452231c2f27f1bd71235a529ca45df7a”,”width”:”18”,”opacity”:”100”,”tint_color”:0,”type”:”image”,”y”:”150”,”x”:”15”,”low_power”:true},
这几行意思很明确,将四个钻石源文件引进,然后设置宽高,旋转50度。参数前面都介绍过不做过多解释
②从14~26行
{“alignment”:0,”text”:”12”,”italic”:false,”type”:”text”,”bgcolor”:”0”,”size”:”28”,”id”:8,”transform”:0,”bold”:false,”color”:”-65536”,”r”:”0”,”font_family”:2,”low_power_color”:”0”,”opacity”:”100”,”y”:”55”,”x”:”140”,”low_power”:true},
{“alignment”:0,”text”:”1”,”italic”:false,”type”:”text”,”bgcolor”:”0”,”size”:”18”,”id”:9,”transform”:0,”bold”:false,”low_power_color”:”0”,”font_family”:2,”r”:”0”,”color”:”-1”,”opacity”:”100”,”y”:”40”,”low_power”:true,”x”:”230”},
{“alignment”:0,”text”:”2”,”italic”:false,”type”:”text”,”bgcolor”:”0”,”size”:”18”,”id”:10,”transform”:0,”bold”:false,”color”:”-1”,”r”:”0”,”font_family”:2,”low_power_color”:”0”,”opacity”:”100”,”y”:”90”,”x”:”280”,”low_power”:true},
{“alignment”:0,”text”:”3”,”italic”:false,”type”:”text”,”bgcolor”:”0”,”size”:”28”,”id”:11,”transform”:0,”bold”:false,”color”:”-65536”,”r”:”0”,”font_family”:2,”low_power_color”:”0”,”opacity”:”100”,”y”:”170”,”x”:”270”,”low_power”:true},
{“alignment”:0,”text”:”4”,”italic”:false,”type”:”text”,”bgcolor”:”0”,”size”:”18”,”id”:12,”transform”:0,”bold”:false,”color”:”-1”,”r”:”0”,”font_family”:2,”low_power_color”:”0”,”opacity”:”100”,”y”:”240”,”x”:”285”,”low_power”:true},
{“alignment”:0,”text”:”5”,”italic”:false,”type”:”text”,”bgcolor”:”0”,”size”:”18”,”id”:13,”transform”:0,”bold”:false,”low_power_color”:”0”,”font_family”:2,”r”:”0”,”color”:”-1”,”opacity”:”100”,”y”:”290”,”low_power”:true,”x”:”230”},
{“alignment”:0,”text”:”6”,”italic”:false,”type”:”text”,”bgcolor”:”0”,”size”:”28”,”id”:14,”transform”:0,”bold”:false,”color”:”-65536”,”r”:”0”,”font_family”:2,”low_power_color”:”0”,”opacity”:”100”,”y”:”285”,”x”:”150”,”low_power”:true},
{“alignment”:0,”text”:”7”,”italic”:false,”type”:”text”,”bgcolor”:”0”,”size”:”18”,”id”:15,”transform”:0,”bold”:false,”low_power_color”:”0”,”font_family”:2,”r”:”0”,”color”:”-1”,”opacity”:”100”,”y”:”290”,”low_power”:true,”x”:”80”},
{“alignment”:0,”text”:”8”,”italic”:false,”type”:”text”,”bgcolor”:”0”,”size”:”18”,”id”:16,”transform”:0,”bold”:false,”low_power_color”:”0”,”font_family”:2,”r”:”0”,”color”:”-1”,”opacity”:”100”,”y”:”240”,”low_power”:true,”x”:”25”},
{“alignment”:0,”text”:”9”,”italic”:false,”type”:”text”,”bgcolor”:”0”,”size”:”28”,”id”:17,”transform”:0,”bold”:false,”color”:”-65536”,”r”:”0”,”font_family”:2,”low_power_color”:”0”,”opacity”:”100”,”y”:”170”,”x”:”35”,”low_power”:true},
{“alignment”:0,”text”:”10”,”italic”:false,”type”:”text”,”bgcolor”:”0”,”size”:”18”,”id”:18,”transform”:0,”bold”:false,”color”:”-1”,”r”:”0”,”font_family”:2,”low_power_color”:”0”,”opacity”:”100”,”y”:”90”,”x”:”30”,”low_power”:true},
{“alignment”:0,”text”:”11”,”italic”:false,”type”:”text”,”bgcolor”:”0”,”size”:”18”,”id”:19,”transform”:0,”bold”:false,”color”:”-1”,”r”:”0”,”font_family”:2,”low_power_color”:”0”,”opacity”:”100”,”y”:”40”,”x”:”75”,”low_power”:true},
这些行就实现了一个功能:给表盘上写上1~12 个小时的文字,同样color取值分别-1 -65536白色和红色,size字体大小,12 3 6 9 这几个都是28 其他都是18还有不是斜体 italic:false, 类型文本type:txt 背景颜色bgcolor:透明 transform:0 大小写转换的0是不转换 1,2 全为大写全为小写。 bold:false也不是粗体。font_family:2 默认的Roboto Light Condensed 字体.好了这也基本介绍完了,x,y跟前面一样
③从27~31行
{“alignment”:0,”text”:”#DE# #DMMM# #Dd# #Dy#”,”italic”:false,”type”:”text”,”bgcolor”:”0”,”size”:”18”,”id”:20,”transform”:0,”bold”:false,”low_power_color”:”0”,”font_family”:2,”r”:”0”,”color”:”-1”,”opacity”:”100”,”y”:”240”,”low_power”:true,”x”:”100”},
{“alignment”:0,”text”:”#BLP#”,”italic”:false,”type”:”text”,”bgcolor”:”0”,”size”:”18”,”id”:21,”transform”:0,”bold”:false,”color”:”-1”,”r”:”0”,”font_family”:2,”low_power_color”:”0”,”opacity”:”100”,”y”:”160”,”x”:”90”,”low_power”:true},
{“id”:0,”is_tinted”:false,”alignment”:4,”height”:”373”,”r”:”#DWFM#”,”hash”:”3afe55e7255f8e1be8e0027229788796”,”width”:”35”,”opacity”:”100”,”tint_color”:0,”type”:”image”,”y”:”155”,”x”:”160”,”low_power”:true},
{“id”:1,”alignment”:4,”is_tinted”:false,”height”:”355”,”r”:”((#Dh#30)+(#Dm#0.5))”,”hash”:”a0d6045a046e85b583400582cc9c6f6e”,”width”:”40”,”opacity”:”100”,”tint_color”:0,”type”:”image”,”y”:”155”,”x”:”160”,”low_power”:true},
{“id”:2,”alignment”:4,”is_tinted”:false,”height”:”320”,”r”:”#DWFSS#”,”hash”:”d832f16ff81f427c47d65f9afebb8864”,”width”:”34”,”opacity”:”100”,”tint_color”:0,”type”:”image”,”y”:”155”,”x”:”160”,”low_power”:false}]
27行描述的对象是preview.png 中的年月日 “text”:“#DE# #DMMM# #Dd# #Dy#” #DE# 是day of week 显示缩写的星期几 #DMMM# month in year ,显示缩写的月份 #Dd# Day in month,一月中的第几天 #Dy# 年 所有就像这样 今天就是“Tue Dec 9 2014”就会显示在你的表盘上了。其他参数上面都讲过这里不再赘述。还有alignment:4,是center对齐,就是320320的中心咯
28行描述的对象是电池电量: “text”:”#BLP#” #BLP# battery level percentage 就是显示例如 93% 的电量。其他参数不做解释前面都讲到过。就是preview.png中表盘中医的电量啦
29,30,31 ,分别描述的是表盘的分针,时针,秒针。 他们的其他参数跟前面都一样,唯一不同的就是选择 r参数。现在下面详细说明。
29行: “r”:”#DWFM#” 就是Rotation value for minute hand ,它描述的是一个图片的旋转根据分钟来旋转
30行: “r”:”((#Dh#30)+(#Dm#0.5))” 这句比较复杂,慢慢解释下 #Dh#是hour in day (1~12 AM/PM) #Dm# minute in hour Dh是当前小时,表盘总共一圈360°,一小时时针走30°,一分钟时针走0.5°,,那么假如现在是7点 35分,那么按照这个公式就是,730°+35*0.5°=227.5°,你把你表盘时间设置为7:35用量角器量下当前时针角度,哈哈不差的哦
31行:”r”:”#DWFSS#” smooth rotation value for second hand,秒针不是一下下的走看起来是连贯的。其他参数不做解释。注意这个参数在0.9.13中才支持。
第四步: description.json详解
这个文件里面只有一行
{“id”:”3d8a3a2296eb9420edbaf556cc083110”,”build_int”:59,”title”:”Luxurious Star of David”,”desc”:””,”build”:”0.90.12”}
id: 后面的为hash值,至于这个值从哪里我还没有发现,我随便生成了一个也可以用,
build_int:我同不知道,但是看到目前的貌似都是59
title 指定表盘名称,会在facer中显示
desc 暂不清楚,估计跟desc script有关这个值貌似都是留空。
build 版本号
当你看到了这里,恭喜你你是一个有毅力的人,也是一个尊重我劳动成果的人。更是一个肯于学习的人。那么你到这里问我,看到这里你还没说真正怎么做呢?这个问题很简单。既然你都看完了上面所有的东西那我就认为你都掌握了。制作步骤分下面几步:
第一步建立文件结构
img文件夹
description.json文件
preview.png文件
watchface.json文件
img文件放入你准备好的表盘背景文件,表针文件,和其他素材,文件名都为文件hash值,并不要带后缀名.
description.json 仿照别人的文件写一个你的title,你的版本号上面都有讲到
preview.png当你做完其他几个文件后再根据整体效果建立预览文件,这个会在你的facer软件中看到这个图片,也可先设计好再做。看你自己
watchface.json,根据你的整体构思,编写资源文件和对象的描述语句,参考别人的基本语法,你就可以写出属于你的表盘。
文中代码部分错位,wp的编辑器真是跟屎一样啊。传上附件供大家参考http://pan.baidu.com/s/1i0ar8
写在最后:至此教程全部写完,以后可能会添加显示天气等的教程。我没有MOTO360手表不保证什么时候添加。这个教程,我没有任何保留的将我所知道的都写了出来。虽然很长很长,但我相信只要你认真看了,你可以任意定制你的表盘。因为我几乎写了所有参数的解释。文中有很多不当之处或者错误之处。朋友们在阅读当中发现请及时指出。
我的联系方式:
email: shuiqingliu14#gmail.com
blog :www.shuiqingliu.com
最后声明:本文为原创文章,未经本人允许禁止一切转载。特此声明。