我们会看到很多页面带有水印,但是怎么实现呢?当然可以有多种实现方式,本文主要讲解在vue项目中基于DOM或者Cavans实现水印效果,当然还有其他的实现方式,比如在原图片的基础上加上水印生成新的图片,但是这需要后端处理。因为要在vue项目中使用,所以我使用自定义指令可以直接对挂载的dom实现水印效果。
本文实现水印的项目环境为:vue + vite + ts
前面专门有一篇讲解vue2.x与vue3.x中自定义指令详解
将水印的指令放到标签上,设置标签的宽高。水印可以放大div标签上,也可以是img标签上。注意:img才有onload方法,div标签么有。
<script setup lang="ts"> import { ref } from "vue"; </script> <template> <div class="index-content" > <div class="watermaker" v-watermark ></div> <!-- <img v-watermark style="width:400px;height:400px" src="../assets/vue.svg" alt=""> --> </div> </template> <style scoped> .watermaker { width: 400px; height: 400px; } .index-content{ width: 100%; height: 100%; } </style>![]()
directives文件
在directives文件下创建waterMark.ts 文件,具体内容实现如下:
import waterImg from "@/assets/vue.svg" const directives: any = { mounted(el: HTMLElement) { //如果el元素是img,则可以用el.onload将下面包裹 const { clientWidth, clientHeight, parentElement } = el; console.log(parentElement, 'parentElement') const waterMark: HTMLElement = document.createElement('div'); const waterBg: HTMLElement = document.createElement('div'); //设置waterMark的class和style waterMark.className = `water-mark`; waterMark.setAttribute('style', ` display: inline-block; overflow: hidden; position: relative; width: ${clientWidth}px; height: ${clientHeight}px;`); // 创建waterBg的class和style waterBg.className = `water-mark-bg`;// 方便自定义展示结果 waterBg.setAttribute('style', ` position: absolute; pointer-events: none;`在这里插入代码片` transform: rotate(45deg); width: 100%; height: 100%; opacity: 0.2; background-image: url(${waterImg}); background-repeat: repeat; `); // 水印元素waterBg放到waterMark元素中 waterMark.appendChild(waterBg); //waterMark插入到el之前,即插入到绑定元素之前 parentElement?.insertBefore(waterMark, el); // 绑定元素移入到包裹水印的盒子 waterMark.appendChild(el); } } export default { name: 'watermark', directives }![]()
directives文件下创建 index.ts文件
import type { App } from 'vue' import watermark from './waterMark' export default function installDirective(app: App) { app.directive(watermark.name, watermark.directives); }
main.ts中全局引入
import { createApp } from 'vue' import App from './App.vue' import directives from './directives' const app = createApp(App); app.use(directives); app.mount('#app');
MutationObserver对水印元素进行监听,删除时,我们再立即生成一个水印元素就可以了,具体方面在下面讲解。
position:relative
position:absolute ,实现这个水印元素覆盖到原始元素的上层,以实现水印的效果。
通过将图片绘制在cavans中,然后通过cavans的toDataURL方法,将图片转为base64编码。
// 全局保存 canvas 和 div ,避免重复创建(单例模式) const globalCanvas = null; const globalWaterMark = null; // 获取 toDataURL 的结果 const getDataUrl = ( // font = "16px normal", // fillStyle = "rgba(180, 180, 180, 0.3)", // textAlign, // textBaseline, // text = "请勿外传", ) => { const rotate = -10; const canvas = globalCanvas || document.createElement("canvas"); const ctx = canvas.getContext("2d"); // 获取画布上下文 ctx.rotate((rotate * Math.PI) / 180); ctx.font = "16px normal"; ctx.fillStyle = "rgba(180, 180, 180, 0.3)"; ctx.textAlign = "left"; ctx.textBaseline = "middle"; ctx.fillText('请勿外传', canvas.width / 3, canvas.height / 2); return canvas.toDataURL("image/png"); };![]()
使用MutationObserver监听dom变化,MutationObserver详细用法之前已经讲过了,详细可见作为前端你还不懂MutationObserver?那Out了
具体监听逻辑如下:
// watermark 样式 let style = ` display: block; overflow: hidden; position: absolute; left: 0; top: 0; width: 100%; height: 100%; background-repeat: repeat; pointer-events: none;`; //设置水印 const setWaterMark = (el: HTMLElement, binding: any) => { const { parentElement } = el; // 获取对应的 canvas 画布相关的 base64 url const url = getDataUrl(binding); // 创建 waterMark 父元素 const waterMark = globalWaterMark || document.createElement("div"); waterMark.className = `water-mark`; // 方便自定义展示结果 style = `${style}background-image: url(${url});`; waterMark.setAttribute("style", style); // 将对应图片的父容器作为定位元素 parentElement.setAttribute("style", "position: relative;"); // 将图片元素移动到 waterMark 中 parentElement.appendChild(waterMark); }; // 监听 DOM 变化 const createObserver = (el: HTMLElement, binding: any) => { console.log(el, 'el') console.log(style, 'style') // console.log(el.parentElement.querySelector('.water-mark'),'el.parentElement') const waterMarkEl = el.parentElement.querySelector(".water-mark"); const observer = new MutationObserver((mutationsList) => { console.log(mutationsList, 'mutationsList') if (mutationsList.length) { const { removedNodes, type, target } = mutationsList[0]; const currStyle = waterMarkEl.getAttribute("style"); // console.log(currStyle, 'currStyle') // 证明被删除了 // (1)直接删除dom // 1.先获取设置水印的dom // 2.监听到被删除元素的dom // 如果他两相等的话就停止观察,初始化(设置水印+启动监控) // (2) 删除style中的属性 // 1 判断删除的是否是标签的属性 (type === "attributes") // 2.判断删除的标签属性是否是在设置水印的标签上 // 3.判断修改过的style和之前的style对比,不等的话,重新赋值 if (removedNodes[0] === waterMarkEl) { console.log(removedNodes[0]) // 停止观察。调用该方法后,DOM 再发生变动,也不会触发观察器。 observer.disconnect(); //初始化(设置水印,启动监控) init(el, binding); } else if ( type === "attributes" && target === waterMarkEl && currStyle !== style ) { console.log(currStyle, 'currStyle') console.log(style, 'style') waterMarkEl.setAttribute("style", style); } } }); observer.observe(el.parentElement, { childList: true, attributes: true, subtree: true, }); }; // 初始化 const init = (el: HTMLElement, binding: any = {}) => { // 设置水印 setWaterMark(el, binding.value); // 启动监控 createObserver(el, binding.value); }; const directives: any = { mounted(el: HTMLElement, binding: any) { //注意img有onload的方法,如果自定义指令注册在html标签的话,只需要init(el, binding.value) el.onload = init.bind(null, el, binding.value); }, };![]()
删除水印标签依然还在,除非删除水印注册的标签才能删除水印,但是这样做毫无意义,因为这样做内容也会全部删除掉。
toDataURL(type, encoderOptions),接收两个参数:
image/png、image/jpeg、image/webp等等,默认为image/png格式
分享此文一切功德,皆悉回向给文章原作者及众读者.
免责声明:蓝蓝设计尊重原作者,文章的版权归原作者。如涉及版权问题,请及时与我们取得联系,我们立即更正或删除。
蓝蓝设计( www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 、平面设计服务、UI设计公司、界面设计公司、UI设计服务公司、数据可视化设计公司、UI交互设计公司、高端网站设计公司、UI咨询、用户体验公司、软件界面设计公司
众所周知,「用户体验五要素」出自Jesse James Garrett 的《用户体验要素》一书:战略层、范围层、结构层、框架层、表现层。
产品设计者和开发者的角度可以对应理解为:为什么做、做到什么程度、这些东西如何组成、规划用户操作行为、如何呈现这些东西。
「Live Activities设计规范」由苹果出品,原文为英文,上一篇已翻译https://www.yuque.com/viola-ddvdh/yb7quv/uwdod71707e4nez8。上篇也提到了个人对其内容的叙述方式存在一点意见。为了更好的记住&理解「Live Activities设计规范」,使用比较熟悉的「用户体验五要素」对内容进行整理。
原文提供的Live Activity定义如下:
“A Live Activity displays up-to-date information from your app, allowing people to view the progress of events or tasks at a glance.”
“Live Activities help people keep track of tasks and events that they care about, offering persistent locations for displaying information that updates frequently. ”
从原文可以提炼出Live Activity显示特点:
1. 内容是频繁更新的、有进度/状态显示的、用户关心的。
2. 内容的信息量是一眼就能看完的程度。
但上述仍是表象,并非实质,接下来思考这几个问题:
1. 为什么显示的是进度/状态频繁更新的内容?
2. 为什么要强调用户关心的?
3. 为什么信息量是一眼就能看完的程度?
没有Live Activity时,频繁更新主要靠push推送。但push容易被其他APP的push覆盖,且随着各种APP的频繁使用,用户获取关键信息的效率和通过push打开APP的次数反而在下降。
进度/状态频繁更新的内容,说明每个状态存在的时间短,如果被覆盖/忽略,同一状态就不再复现,用户所关心的,或APP所希望用户关心的,就看不到了。比如:什么时候取外卖、待付款、上传成功等等。
当下我们所处的时代是信息泛滥的时代,需要对信息作精简,但用户的操作是可以多条线进行的,比如比如边看剧边吃饭、上班摸鱼/等外卖、比如听音乐的时候写作。
信息内容和量是官网一直在强调的,需要精简,只展示用户需要的,基本达到一眼看完的程度,目的就是知道变化的是什么,当前状态是什么。
分析了这么多,大胆推测一下Live Activity的设计初衷是:快&准确&轻。而终极目的是打动用户,形成好体验,进而推动口碑和销售;为各APP提供新的通知形式,互惠互利。当然Live Activity在一定程度上也弥补了硬件上的缺憾。
关于这个层次相当于规定功能范围&信息边界限制,就是什么要,什么不能要。这部分的信息官网给出许多,在此将其分类梳理如下,为避免大家不好查找官网/译文对应出处,在句未已标注。
1. 仅iPhone支持,iPadOS、macOS、tvOS或watchOS不支持。(源自:平台注意事项)
2. 非iPhone14的仅针对iOS16有锁屏Live Activity展示。(源自:什么是Live Activity-锁屏)
3. 支持用户手动清除锁屏状态下的Live Activity。(源自:实际操作)
4. 支持用户直接关闭对应APP的Live Activity。(源自:最佳实践方式第3/c条)
5. 支持Live Activity自动开始&结束。(源自:最佳实践方式第6/f条)
6. 限制跟踪活动/状态时长不超过8小时。(源自:最佳实践方式第1/a条)
7. 限制活动/进程结束后展示时长不超过4小时。(源自:最佳实践方式第8/h条)
8. 支持更改背景颜色&不透明度。(源自:设计有用的Live Activity第5/e条)
9. 限制内容布局。(源自:设计有用的Live Activity第5/e条)
10. 限制不同设备的展示尺寸。(源自:规范)
1. 避免在Live Activity中显示敏感信息。(源自:最佳实践方式第4/d条)
2. 避免在Live Activity中显示广告和促销活动。(源自:最佳实践方式第5/e条)
3. 只提供正在进行的任务/事件的关键摘要。(源自:最佳实践方式第2/b条)
4. 在任务/活动结束前,给用户提供关闭Live Activity按钮。(源自:最佳实践方式第6/f条)
5. 点击Live Activity直接定位到对应页面,无需用户二次导航。(源自:最佳实践方式第7/g条)
6. 考虑在活动结束后,锁屏上在合理时段后自动删除Live Activity。(源自:最佳实践方式第8/g条)
(个人猜测)由于是提供一个展示区域,且展示区域有限,所以对于层级架构,一级展示什么,二级展示什么,各阶段展示什么,这些都没有做明确规定&建议。各家APP可以根据自身实际情况进行设计。
通过Live Activity的展示形式,可以总结为2点:吸引、查看(摘要&详情)。
1. 一般是在原深感摄像头两侧展示(电话会直接展示扩展型),分为紧凑型和最小化。
2. 紧凑型在仅有一个活动/事件的时候展示,虽被原深感摄像头分割两端,但仅作为一条信息展示,为了视觉上的统一,这里的颜色不支持开发设置,使用的是系统默认色值。
3. 最小化在存在多个活动的时候展现,左侧和原深感摄像头粘连,右侧独立成岛。
4. 不管是紧凑型,还是最小化,都可以通过点击原深感摄像头区域,进入APP内页,或者长按唤出扩展型。
1. 进入内页的查看基本就是各家显神通了,这里主要讲扩展型和锁屏。
2. 原则上是不支持在扩展型和锁屏做复杂操作的,基本点击是进入APP。
3. 扩展型是用户长按紧凑型/最小化唤起的展示区域,内容是可以自定义的,当然官方也给了相应的建议,具体如下。内容信息种类多的可以采用这种信息左中右排布,底部预留大按钮。内容信息少的可以采用左内容右操作的方式。
4. 根据一致性原则,锁屏展示的布局框架应该与扩展型差不多,同样可以点击打开APP。只是在锁屏状态如果有多个任务同时进行,是会全部展示的,所以要注意品牌的传递,避免用户混淆服务方。
对于如何呈现这些东西,苹果还是写了很多建议,确保视觉上的一致性和美观。
1. 紧凑型状态下,为了保证两侧信息的连贯,除了语句阅读连贯,还需要在图形和颜色上具有一致性,视觉上连贯。
2. 锁屏状态下的背景是可以自定义颜色、图像、不透明度的,当然文字的色值和不透明度也是可以定义的。这就涉及到两者间的对比度对信息阅读的影响。
3. 设计师不仅要考虑最佳状态,还有深色&浅色模式下的,以及不同环境光、设备亮度下的显示。还有一点很容易忽视的,就是在用户自定义的墙纸下显示的效果。不仅要注意信息获取,还需要考虑美感问题。
1. 紧凑型和扩展型之间的布局要保持一致,两者间的变化过渡效果是可以预测的。
2. 一般来说,扩展型和锁屏状态下的信息间标准间距是20pt。
3. 在某些情况下,例如图形和按钮,您可能需要使用更紧凑的边距,以避免挤满边缘或形成混乱的外观。
1. 内容和Live Activity边缘之间的边距需要保持一致,请遵循SwiftUI规则。
1内容和Live Activity边缘之间的边距需要保持一致,,发现以圆角边界为测距点得到的间距关系较为舒适。即:圆形/大致为圆形的图形保持上下,3. 以及左侧或者右侧间距一致即可;方形/大致为方形的图形保持圆角边界与容器圆角边界垂直对齐即可。同一位置的多个图形圆角需要相对统一,才能确保间距的一致性。
需要适应不同机型的尺寸。具体的尺寸规范如下。
动态岛使用44个点的角半径,其圆角形状与原深感摄像头相匹配。
下表中列出的所有值均以pt为单位。
ps:左侧为宽度,右侧为高度。
以上就是整理分析的全部。
在整理分析过程中加强了对「用户体验5要素」各个层划分的理解,也对Live Activity在各个层次上的要求更加明确。
不太爱看书,看了老忘,就很容易失去信心,垂头丧气、一蹶不振。
比较喜欢做图,把信息间的逻辑以图示化的方式表现出来,能加强理解,后期回顾也会比较舒心。
所以就有了这个系列——阅读图示化。
可能会出得很慢,画图比较费时间,想着怎么展示信息间的逻辑也很费时间。
基本是按着小节一块内容对应单图/多图。
基本一张图是一个完整的知识点。
当今提到促进业务增长,尤其是有关互联网行业,总是绕不开B端设计。那么今天我们来挖一挖B端设计到底牛在哪里。
B端设计是指针对企业的终端用户的产品设计,包括适用于消费者、企业、政府、行业等等市场的协同、全方位的客户体验设计,例如产品UI/UX设计、信息可视化设计等等。B端设计是提供终端用户新的解决方案,注重以客户的需求为导向,通过数据分析、可视化、流程优化等手段来进行产品设计。
在一个产品设计中,要考虑到用户的体验,UI/UX有着至关重要的作用,它能够把产品从用户的角度出发,将用户直接引入到设计之中,使用户步入终端,真正成为使用者。
此外,B端设计还要注重对业务流程的优化,例如在订单管理系统的设计中,需要把客户的需求分析清楚,尽可能用最少的步骤帮助客户快速进行订单操作,增加操作效率;同时,也需要考虑到如何将整个管理系统融入到业务流程之中,使其成为一个可持续发展的解决方案。
此外,B端设计还需要考虑系统安全性和可用性。系统安全性指的是在设计过程中重视数据安全,例如考虑不同用户的权限,避免未经授权的访问以及防止误操作等;而系统的可用性则指的是系统操作的一致性,即如何在使用中满足客户的需求,在系统功能上保障系统的完备性和易用性,为用户提供更方便的操作体验。
正确的B端设计应包括:用户界面设计、业务流程的优化、系统安全性以及可用性的考虑等。
用户界面设计的目的在于提供简单易用的用户界面,以满足客户需求,提高用户体验。
业务流程优化则是确保系统能够有效地协调用户间的沟通,使用户流程更加高效、可靠。
系统安全性考虑需要重视数据安全,增加对不同用户权限的考虑,以避免未经授权的访问以及误操作。
而系统可用性方面,则需要系统操作一致性,保障功能的完整性和易用性,使用户操作更加便捷。
用户界面设计还需要考虑跨浏览器的兼容性,以确保用户能够在不同的终端上获得有效的使用体验。此外,对于功能性更强的应用,还需要考虑响应速度、网络请求数和业务性能等方面的优化,以便在处理大量的信息时能够有效地完成任务。
对于不同的用户群体,应当提供相应的交互界面设计,例如考虑弱智使用者和视觉障碍者,以及婴幼儿等特殊群体。此外,可以通过支持多种语言、国家文化差异和地域语言来优化用户体验。
B端设计原则可以帮助企业更好的把握商业机遇,推动业务发展。
首先,应当按照核心业务找出客户需求,深入挖掘,从客户视角出发,明确目标。
其次,要强化设计意识,注重交互性,利用技术手段和平台将功能元件组合在一起,以便更好地解决客户面临的问题和满足客户的需求。
最后,对产品的功能、使用效果和用户体验进行定期的测试评估,根据反馈进行变更和优化,以满足客户的需求。
为实现B端设计的潜在价值,可以采用多重方法,比如从创新的角度增加产品的附加值,加强功能和服务体验,提升网站可用性,优化页面布局,提高页面加载速度等。
另外,还可以改进客户体验,通过可视化或语音技术提升网站和移动应用的交互性,以便让客户更容易获取想要的信息和服务。
此外,可以加强产品的社会化和移动性,以便更好地满足客户的需求,从而获得更多的潜在价值。
对于B端设计来说,还要考虑技术层面的因素。
首先,应根据客户使用情况进行系统优化,以提高系统效率。
其次,要重视人机交互技术,尽可能提供给用户更好的界面体验,并利用智能技术提升用户体验。
此外,应结合实际情况,采用合适的网络技术和安全技术,提升网站的安全性。
最后,还要将设计与市场营销结合起来,通过有效的营销手段,提高客户购买意愿,以获得更多的潜在价值。
B端设计要考虑的技术层面因素有:系统优化、人机交互技术、网络技术和安全技术以及营销手段。这些都是为了能够更好地满足客户的需求,并获得更大的价值。
首先,淘宝的B端设计把价值的提升放在了首位。它通过实时监测用户行为来分析用户习惯,以实现实时调整,提升客户体验。此外,淘宝的营销手段也让它的业务获得了极大的成功。
另外,微信也是一个优秀的B端设计案例。它引入了更多的人机交互技术,以有效沟通用户,同时也提供更安全、便捷的服务,大大提升了用户体验,获得了广泛的应用。
总之,优秀的B端设计不仅能优化用户体验,还可以带来更多的商业价值。
从用户体验角度来看,优秀的B端设计应包括系统优化、人机交互技术、网络技术和安全技术,这样可以给用户提供更流畅的体验,更快的响应速度和更好的安全保障。
此外,B端设计还应该拥有一套完整和灵活的营销手段,帮助企业获得更多的客户价值,以提升品牌影响力和竞争力。
要做好B端设计,一个重要的方面是把用户群体的心理需求和行为习惯结合起来,设计出更具吸引力的产品界面。例如,可以通过实时调整产品配置、设定营销活动等手段来满足不同用户群体的需求。
另外,为了提升用户体验,应该使用更智能化的人工智能(AI)技术,帮助企业更好地分析用户行为,从而更有针对性地进行产品调整。
总而言之,B端设计的成功关键在于结合用户群体的心理需求和行为习惯,并利用智能化的AI技术对用户行为进行分析,只有这样才能设计出更具吸引力的产品界面,满足不同用户群体的需求,并提升用户体验。
在企业开发B端产品之前,应该先进行大量的市场调研,以便弄清楚用户的心理需求和行为习惯,这也是设计成功的前提。在制定设计思路时,应该结合用户需求和行为习惯,并加入智能化AI技术,以有效调整产品界面,使其更具吸引力。在可行性研究阶段,应该采用多种方法,以测试产品整体性能,包括安全性、可靠性等,确保系统可以正常运行,避免潜在风险的发生,为用户的体验提供完善的保障。市场调研是设计成功的先决条件。除了市场调研,企业还应该采用新颖的营销策略,以拓展客户群,丰富产品服务,提升用户体验,实现B端设计成功。
在讲开源设计前,我们或许可以先讲讲开源一词是指什么。
开源全称开放源代码,开源软件最大的特点是开放,也就是任何人都可以得到软件的源代码,加以修改学习,甚至重新发放,当然是在版权限制范围之内。虽然开源一词最初是为软件开发而创造的,但现如今开源所涉及的领域也极其广阔,并不只是包括软件领域,如医药领域的药物开发开源、文化领域的书籍到期开源等等所以开源设计已包含了更广泛的含义,它包括了由任何人或者团队自由共享、协作的设计方案、项目、产品。
我们来看几个大型开源的设计了解一下~
Ant Design
阿里的开源系统后台组件库
https://ant.design
百度推出的开源图表
https://echarts.apache.org/
全球知名图片开源平台
https://unsplash.com
免费(大部分是):开源设计的一个关键要素是它们通常(但不总是!)免费。这是一个重要因素,因为闭源设计通常需要花费不菲的价格或者冒着侵犯版权的风险去使用。
思想碰撞:更多的设计师或者创意爱好者共同为一个创意提出自己的见解和再设计。
设计开源领域广阔:设计开源领域也几乎涵盖了所有的设计和创意领域如平面设计、三维设计、用户体验设计、环境设计、建筑设计、服装设计、插画、动画设计等等
但是许多人可能会有一个疑问,开源设计和以往的素材网站或者源文件售卖网站有什么区别呢?
在我看来,开源网站与传统售卖设计资源的网站最大的区别是开放与共建,以figma的社区为例,作者发布作品后,任何人都可以对其作品进行redesign甚至remix,这极大的提高了设计师的兴趣,每个人都希望自己的作品能被他人看到,也希望自己的创意能与他人的创意进行更好的结合,这是一个多么美好的场景。而传统网站只是冷冰冰的展示文件售卖资源,缺少了设计中的灵魂。
那说了这么多,开源设计到底有哪些优势呢?
提升设计效率:设计师不应花费时间去解决别人已经解决的问题,比如当我设计一个新项目时,无需从零开始设计系统组件,可以直接使用Ant Design、Ant Mobile Design等现有组件库。
增加学习机会:通过开源社区,设计人员可以从其他人所做的项目中学习,并与专业人员交流经验。
提高设计质量:设计师自己看本人作品时,往往是身在其中不知如何下手,而将作品发布到更广泛的社区有助于设计师获得有价值的反馈以改进他们的作品。
提升品牌价值:对设计开源后,公司品牌能在某些领域内获得传播,提升品牌价值。并且在招募人才时也能成为有吸引力的一项条件。
提升个人价值:一个设计师想要提升个人价值和影响力,可以用开源作品来在行业内获得一定口碑,甚至直接将用户流量转化为订单,或许是更简单且容易的事情。
从这些优势中不难发现,在开源生态中,我们的作品不再是一座孤岛,通过互联网,我们的作品可以和任何人进行链接并且产生共鸣,提升品牌和个人的价值,所以每个人都值得感受开源的美好。
但开源的同时不可避免的会带来许多新的问题和挑战,让我们一起来看一下。
知识产权问题:在开源社区中,设计师可能不清楚其创作的知识产权。因此,他们可能会不自知地侵犯其他设计师的知识产权。
设计门槛问题:设计开源意味着设计师的门槛变低,任何人都可以随意使用开源的设计项目,导致设计师不再愿意花心血创作。
设计师竞争力下降:开源设计意味着普通的设计内容已不需要单独的设计师来完成,顶尖设计师的机会会更多,而普通设计师的竞争力会明显下降。
随着这些挑战的来临,如何更好的面对设计领域的开源是值得深思的问题,既要保护设计师的自身利益,也要让设计行业在开放、共享的环境下拥抱变革,所以在未来的道路上,我们每个人都可以尝试用自身的方法去探索未来,让每个人都能成为时代浪潮中的一朵浪花。
什么是“有驾”
【有驾】是百度旗下的汽车信息与服务平台,累计用户超5.3亿,致力于为用户提供真实、可靠的看选买车服务,以及为车企和经销商提供从品牌到效果的一站式互联网营销解决方案。
现状分析
有驾品牌在孵化初期,重点是在用户词建立品牌感知。所以我们提取“有驾“的字形做为品牌符号,减少歧义,强化用户的感知。
但是随着品牌持续运营进入新的阶段,我们发现现有的设计无法满足后续的运营诉求了,主要体现在:
品牌logo:不能体现汽车的行业属性,缺乏成体系的品牌符号和VI体系,色彩上也不够符合时下潮流的年轻配色体系。
品牌活动:品牌关联度弱,活动维度单一。
项目概述
因此,我们重新梳理有驾的品牌定位与调性,借助本次品牌升级,打造有驾差异化风格,形成独有的视觉印记。
因为用户对于旧的logo已有一定的认知。所以此次改版的目标在保持固有用户认知,在原有基础上进行品牌标识的探索及应用,以强化品牌感知,提升品牌的竞争力,整合业务资源做心智触达。
前期分析
前期我们对汽车垂类的竞品进行了一轮调研,并且结合有驾的用户群里,寻找有驾品牌的差异点。
有驾用户群体年轻化为主,普遍具有高学历,集中在新一线二线城市。
通过以上在用户、行业及行业趋势等多唯独的信息搜集后,我们确定了有驾品牌设计的四个核心关键词:年轻、科技、未来、专业。
建立体系
在明确设计方向后,我们梳理了线上线下的所有品牌触点,结合前期的调研结论,汇总出了有驾设计系统的完整框架,以确保品牌设计的完整性和灵活适用性。
设计落地
基于前期分析洞察结论,我们在继承圆形和车形的基础上,对品牌符号与icon进行了大量的方案探索。从图形、质感等方面切入,简化图形形态,尝试不同的形态呈现的视觉感受和气质。最终确定了全新品牌logo方案。
相对于升级前,新版的logo加入汽车元素,解决升级前logo的行业属性不明确的问题,让产品app的行业属性更加直观。同时增加品牌符号做为底纹,辅以有驾的圆形符号成为品牌核心的一部分。强化有驾的品牌基因。
符号提炼
确定品牌logo后,为了确保品牌能够更好的拓展应用,进行了品牌符号的提炼。并为了延续之前的品牌调性。所以辅助图形延续了之前的圆环造型,造型偏向轮胎;在不破坏原有型的基础上,加入一些折角的质感的变化,使图形变化更加丰富,更有识别度。
设计语言
为了更好的触达到各业务场景,所以我们对视觉风格进行了探索和拓展。分别以浅色与深色作为主要探索方向,以适配不同的落地场景。结合有驾的年轻化,科技感的设计目标,探索出以下三种质感呈现:
符号拓展
在提取的形状基础上进行变形,增加折叠细节。在大事件活动,海报等场景使用,增加品牌关联度。
设计字体
结合全新的品牌定位,我们也优化了有驾的品牌字体,从细节出透出有驾的品牌感知。
品牌手册
新的品牌需要一套更全面的品牌系统来满足不同场景下的业务拓展需求。
目前我们也对现有的品牌手册进行拓展和完善,同步到业务方,以便更好的保证各业务场景触点下品牌的认知和统一,达到提质增效的目的。
品牌落地
除了对品牌对角度的塑造和升级,我们更积极的把品牌渗透到活动、栏目包装、大事件运营、品牌海报等各维度场景中,让有驾品牌形象更加立体多元。
结语
目前有驾品牌升级已经取得阶段性成果,沉淀出更加完善的品牌资产,不仅提升设计效率保证全链路的品牌曝光,也为业务规模化打下基础。之后我们也将不断完善和扩充品牌资产,将设计成果不断落地到业务中,细化业务目标并与设计目标紧密结合,多维度助力业务的高速发展。
从事体验设计这么多年,经历过多款B端和C端产品的体验设计,有了一定的个人感悟。由于两者用户群体、使用场景、产品定位等方面的不同,让两者的体验设计策略也存在较大的差异。但是无论是B端还是C端产品,有一个共同的体验目标就是“提升用户的操作效率”。甚至在一定程度上,C端产品比B端产品要求更高。
为什么这么说呢?
因为C端产品面临激烈的市场竞争,如果效率方面存在明显的不足,用户很容易就转向其他平台了。而B端产品一旦部署上线,不菲的产品价格,平台切换的风险,数据迁移的成本等因素,很容易形成产品的护城河。虽然用户内心已是万马奔腾,但是依旧要自己摸索尝试、查看文档、或者请教别人来完成工作任务。
今天我们了解下C端产品用户行为路径中提升效率的4种方法。
用户行为探知,就是根据用户的操作行为或特定的时间,系统给出相应的推荐操作。
最常见的就是截屏操作产生的行为引导,目前主流的产品应用都会做出分享功能提示。在淘宝中,由于商品链接无法在微信中直接分享,所以淘宝对可能的用户分享行为都进行了设计优化。
例如用户在商品页面截屏时,系统会自动复制淘口令,既方便用户分享给好友,又方便了对方快速获取商品信息,避免了图片分享过程中的复杂操作。同样微信在用户发信息时,会自动提示是否要发送截图内容,减少了用户选择图片等操作流程,提升了用户效率。
(左图:淘宝截屏提示 右图:微信提示截屏信息)
高德地图在特定时间段,开启导航时会默认给出“上班路线”的按钮,方便用户快速导航。此外还在地址中增加了“常搜”标签,根据当前地址优先显示常搜的地址,帮助用户快速完成导航设定。
用户行为引导,就是通过用户行为流程分析,在用户路径中增加相关功能的曝光和引导,让流程更加流畅,从而提高用户的操作效率。
淘宝购物商品详情页中,在最后几张商品图片中植入了评价信息和入口,更加符合用户的心智,引导性也更强。同时用户可以直接选择自己喜欢的款式查看商品评价,操作效率也更高。
而且增加评论引导后,实现了用户在首屏就可以了解商品、价格和用户评价,有利于用户对商品作出初步的购买决策,从而提高用户效率。
相比之下,专门的评价模块进入后默认显示全部商品的评价信息,用户需要手动选择才能查看自己喜欢的商品款式的评价信息,无形中拉长了用户的行为路径,增加了用户操作成本。
在今日头条中,搜索行为与资讯内容绑定。用户在浏览的资讯后,资讯下方会自动显示搜索关键词,可以帮助用户更快捷的进行搜索操作。
同样在热榜资讯下方增加了详情提示,引导用户去查看事件详情。
(左图:搜索关键词推荐 右图:热榜引导)
手机产品屏幕的空间相对较小,展示内容有限。因此需要根据用户行为,将相关功能聚合,让用户在一屏中可以获取更多的信息,从而提高用户效率。
在天猫部分商品详情页中,将商品参数集合在了商品名称右侧,保证了用户在不滑动屏幕的情况下,就可以直接读取商品参数。方便了用户快速了解商品信息,提升了用户的购物效率。
考拉海购则在部分商品首屏中,直接分类展现出了商品的型号和款式分类,并且实现了商品价格联动,提升了用户获取信息的效率。
减少用户的记忆成本,最好的方法就是让系统产生记忆。因此大多数APP都会提供历史浏览记录等功能,方便用户查找相关信息。而内容型产品为了更好的提高用户操作效率,则是将用户行为记忆直接保留在内容层面上。
我们常见的音乐类产品会留存音乐的播放进度,用户点击后就可以直接再次播放。
(左图:喜马拉雅 右图:网易云音乐)
微信公众号文章阅读时,会对用户阅读位置增加锚点。用户再次阅读时,自动定位到上次退出时位置,从而提高用户的阅读效率。
微信“看一看”进入时,内容会自动刷新,提供更多新的内容给用户,为了帮助用户更好地区分新内容,微信增加了浏览位置提醒。
同样对于用户未完成的文章内容,用户再次进入时,今日头条会给出继续阅读的提示信息,方便用户快速操作。
在提升用户效率时,我们需要关注用户场景和行为路径,从而寻找到更多的效率提升突破口,主要包含以下3个注意点:
1、明确用户的行为路径,寻找用户核心关切点,提升用户效率;
2、转移用户操作成本,让系统承担更多的行为判断和用户引导;
3、用户行为聚合时,应当集中关键的行为信息,避免对用户核心行为造成干扰;
以上就是我对提升用户效率方法的分析和总结,欢迎大家留言交流。
作者:子牧先生
转载请注明:站酷
分享此文一切功德,皆悉回向给文章原作者及众读者.
免责声明:蓝蓝设计尊重原作者,文章的版权归原作者。如涉及版权问题,请及时与我们取得联系,我们立即更正或删除。
蓝蓝设计( www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 、平面设计服务、UI设计公司、界面设计公司、UI设计服务公司、数据可视化设计公司、UI交互设计公司、高端网站设计公司、UI咨询、用户体验公司、软件界面设计公司
1. <!-- 弹出框 --> <el-dialog :title="titleMap[dialogStatus]" :visible.sync="dialogFormVisible"> <el-form :model="form" :rules="rules" ref="form"> <el-form-item label="商品名称" prop='goodsName' style="width:40%"> <el-input v-model="form.goodsName" auto-complete="off" placeholder="请输入商品名称" size="medium"></el-input> </el-form-item> <el-form-item label="商品图片" prop='goodsImg'> <el-upload action="uploadAction" list-type="picture-card" :on-preview="handlePictureCardPreview" :on-remove="handleRemove" :limit="1" :show-file-list="true" name="img" ref="upload" :data="form" accept="image/png,image/gif,image/jpg,image/jpeg" :headers="headers" :on-exceed="handleExceed" :auto-upload="false" :on-error="uploadError" :before-upload="handleBeforeUpload" :on-change="changeFile"> <i class="el-icon-plus"></i> </el-upload> <el-dialog :visible.sync="dialogVisible"> <img width="50px" :src="dialogImageUrl" alt=""> </el-dialog> </el-form-item> <el-form-item label="商品对应积分" prop='goodsIntegral'> <el-input v-model="form.goodsIntegral" auto-complete="off" placeholder="请输入积分" size="medium" type="number"></el-input> </el-form-item> </el-form> <div slot="footer" class="dialog-footer"> <el-button @click="cancel">取 消</el-button> <el-button type="primary" @click="uploadFileFun('form')">确 定</el-button> "注意uploadFileFun('form') 括号内记得带引号不然可能会报validate is not defined" </div> </el-dialog>
2.data部分
data() { return { //新增和编辑弹框标题 titleMap: { addStore: '新增商品', editStore: "修改商品" }, dialogStatus: "", //新增编辑弹出框 dialogFormVisible: false, dialogVisible: false, //表格数据 tableData: [], form: { id: '', goodsName: '', goodsImg: '', goodsIntegral: '', }, rules: { goodsName: [{ required: true, message: '请输入商品名称', trigger: 'blur' }], goodsIntegral: [{ required: true, message: '请输入商品积分', trigger: 'blur' }], }, headers: { Authorization: 'Bearer ' + window.localStorage.getItem("token") }, dialogImageUrl: '', //图片回显 uploadFiles: '', //formData img 文件 goodsId: '', //判断是新增还是编辑 },
// 上传文件之前的钩子 handleBeforeUpload(file) { console.log('按钮', this.titleMap) if (!(file.type === 'image/png' || file.type === 'image/gif' || file.type === 'image/jpg' || file.type === 'image/jpeg')) { this.$notify.warning({ title: '警告', message: '请上传格式为image/png, image/gif, image/jpg, image/jpeg的图片' }) } let size = file.size / 1024 / 1024 / 2 if (size > 2) { this.$notify.warning({ title: '警告', message: '图片大小必须小于2M' }) } }, //图片上传超过数量限制 handleExceed(files, fileList) { this.$message.error("上传图片不能超过1张!"); }, handleRemove(file, fileList) { this.$message.error("删除成功!"); }, // 图片上传失败时 uploadError() { this.$message.error("图片上传失败!"); }, //预览图片 handlePictureCardPreview(file) { this.dialogImageUrl = file.url; this.dialogVisible = true; }, //文件改变时 on-change方法 ,fileList[0].raw 就是传给后端的值 //filelist这个对象里面有很多属性,我们上传文件时,实际上传的是filelist列表中每一项的raw,只有raw可以正常上传, 获取到文件后,需要定义变量保存文件。所以需要获取filelist中的raw进行保存。 //这里我用的formdata上传多文件,console打印formdata,文件在控制台中显示的格式为binary。 changeFile(file, fileList) { this.uploadFiles = fileList[0].raw }, uploadFileFun(formName) { this.$refs[formName].validate((valid) => { let fd = new FormData(); fd.append('id', this.form.id); fd.append('goodsName', this.form.goodsName); fd.append('goodsIntegral', this.form.goodsIntegral); fd.append('img', this.uploadFiles); let config = { headers: { 'Content-Type': 'multipart/form-data' } } 根据goodsID判断是编辑提交还是新增提交,主要针对新增编辑使用同一个弹框 if (valid && !this.goodsId) { this.$axios.post("接口地址", fd, config).then(res => { if (res.data.success == true) { this.dialogFormVisible = false this.$message({ message: res.data.msg, type: 'success' }); //新增完清空表单内容 setTimeout(() => { this.$refs.form.resetFields(); }, 200) this.reload() } else { this.$message.error(res.data.msg); } }).catch(res => { console.log(res) }) } else { this.$axios.post("接口地址", fd, config).then(res => { if (res.data.success == true) { this.dialogFormVisible = false this.$message({ message: res.data.msg, type: 'success' }); //编辑完清空表单内容 setTimeout(() => { this.$refs.form.resetFields(); }, 200) this.reload() } else { this.$message.error(res.data.msg); } }).catch(res => { console.log(res) }) } }) }, add() { this.dialogStatus = "addStore" this.dialogFormVisible = true this.goodsId = "" //新增商品是商品ID为空 }, // 取消 cancel() { this.dialogFormVisible = false this.$refs[formName].resetFields() }, //编辑 handleEdit(index, row) { this.form = this.tableData[index] this.dialogStatus = "editStore" this.goodsId = row.id this.currentIndex = index this.dialogFormVisible = true },
分享此文一切功德,皆悉回向给文章原作者及众读者.
免责声明:蓝蓝设计尊重原作者,文章的版权归原作者。如涉及版权问题,请及时与我们取得联系,我们立即更正或删除。
蓝蓝设计( www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 、平面设计服务、UI设计公司、界面设计公司、UI设计服务公司、数据可视化设计公司、UI交互设计公司、高端网站设计公司、UI咨询、用户体验公司、软件界面设计公司
在我上一篇写的Node.js实现简单的POST请求
里面POST请求接受参数需要写两个事件,这难免有些不太方便
如果我们用formidable来接受参数的话,会变得特别方便。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> </head> <body> <form class="upload" action="shangchuan" enctype="multipart/form-data" method="post"><!-- 上传接口是/shangchuan --> <p> 请上传一个头像 <input type="file" name="wenjian"> </p> <p> <input type="submit" value="提交"> </p> </form> </body> </html>![]()
安装依赖,执行下面这三句npm语句
npm install finalhandler --save
npm install serve-static --save
npm install formidable --save
之后会自动生成下面这个package.json文件
{
"dependencies": {
"finalhandler": "^1.1.1",
"formidable": "^1.2.1",
"serve-static": "^1.13.2"
}
}
var finalhandler = require('finalhandler') var http = require('http') var serveStatic = require('serve-static') var url = require('url') var fs = require('fs') var querystring = require('querystring') var formidable = require('formidable') var path = require('path') // Serve up public/ftp folder //配置静态资源服务器,将public文件夹静态化出来 var serve = serveStatic('public', {'index': ['index.html', 'index.htm']}) // Create server var server = http.createServer(function onRequest (req, res) { //路由 var pathname = url.parse(req.url).pathname; if(pathname == '/shangchuan'){ //创建一个表单的实例,formidable var form = new formidable.IncomingForm(); //设置上传的文件存放在哪里 form.uploadDir = './uploads'; //处理表单 form.parse(req,(err,fields,files) => { //fields 表示普通控件 //files 表示文件控件 if(!files.wenjian){ return; } if(!files.wenjian.name){ return; } var extname = path.extname(files.wenjian.name);获取文件的扩展名,便于下面修改上传后的文件名字 //改名 fs.rename(files.wenjian.path, files.wenjian.path + extname,() => { res.end('上传成功') }) // console.log(fields); }) return; } serve(req, res, finalhandler(req, res)) }) // Listen server.listen(3000); console.log('服务已经启动在3000端口');![]()
会看到这个页面
然后选择任意文件点击提交
会发现在很短的时间内你的文件会提交成功在你的uploads文件夹下。
分享此文一切功德,皆悉回向给文章原作者及众读者.
免责声明:蓝蓝设计尊重原作者,文章的版权归原作者。如涉及版权问题,请及时与我们取得联系,我们立即更正或删除。
蓝蓝设计( www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 、平面设计服务、UI设计公司、界面设计公司、UI设计服务公司、数据可视化设计公司、UI交互设计公司、高端网站设计公司、UI咨询、用户体验公司、软件界面设计公司

蓝蓝设计的小编 http://www.lanlanwork.com