首页

前端开发——NodeJs学习

seo达人

如果您想订阅本博客内容,每天自动发到您的邮箱中, 请点这里

NodeJs基础
nodejs的本质:不是一门新的编程语言,nodejs是javascript运行在服务端的运行环境,编程语言还是javascript

global模块-全局变量
Node.js 中的全局对象是 global, 类似于浏览器中的window

常用的global属性

console: 用于打印日志
setTimeout/clearTimeout: 设置清除延时器
setInterval/clearInterval: 设置清除定时器

__dirname: 当前文件的路径,不包括文件名
__filename: 获取当前文件的路径,包括文件名

//与模块化相关的,模块化的时候会用到
require
exports
module

除了global模块中的内容可以直接使用,其他模块都是需要加载的。
其他模块不是全局的,不能直接使用。因此需要导入才能使用。
fs模块
fileSystem-- 文件系统,提供了一系列操作文件的API接口,可以方便我读写文件

读取文件
语法:fs.readFile(path[, options], callback)

方式一:不传编码参数

//参数1: 文件的名字
//参数2: 读取文件的回调函数
  //参数1:错误对象,如果读取失败,err会包含错误信息,如果读取成功,err是null
  //参数2:读取成功后的数据(是一个Buffer对象)
fs.readFile("data.txt", function(err, data){
  console.log(err);
  console.log(data);
  // 可以通过data.toString() 把二进制数据转成文本,当然前提是读取的文件本来就是文本,如果是图片获取的二进制就无法转换成文本
});

方式二:传编码参数

//参数1: 文件的路径
//参数2: 编码,如果设置了,返回一个字符串,如果没有设置,会返回一个buffer对象
//参数3: 回调函数
fs.readFile("data.txt", "utf8",function(err, data){
  console.log(err);
  console.log(data);
});

关于Buffer对象

1. Buffer对象是Nodejs用于处理二进制数据的。
2. 其实任意的数据在计算机底层都是二进制数据,因为计算机只认识二进制。
3. 所以读取任意的文件,返回的结果都是二进制数据,即Buffer对象
4. Buffer对象可以调用toString()方法转换成字符串。

写文件
语法:fs.writeFile(file, data[, options], callback)

//参数1:写入的文件名(如果文件不存在,会自动创建)
//参数2:写入的文件内容(注意:写入的内容会覆盖以前的内容)
//参数3:写文件后的回调函数
fs.writeFile("2.txt", "hello world, 我是一个中国人", function(err){
  if(err) {
    return console.log("写入文件失败", err);
  }
  console.log("写入文件成功");
});
1
2
3
4
5
6
7
8
9
注意:

写文件的时候,会把原来的内容给覆盖掉
追加文件
语法:fs.appendFile(path, data[, options], callback)

//参数1:追加的文件名(如果文件不存在,会自动创建)
//参数2:追加的文件内容(注意:写入的内容会覆盖以前的内容)
//参数3:追加文件后的回调函数
fs.appendFile("2.txt", "我是追加的内容", function(err){
  if(err) {
    return console.log("追加文件内容失败");
  }
  console.log("追加文件内容成功");
})


思考:如果没有appendFile,通过readFile与writeFile应该怎么实现?

文件同步与异步的说明
fs中所有的文件操作,都提供了异步和同步两种方式

异步方式:不会阻塞代码的执行
同步方式:会阻塞代码的执行
//同步方式
console.log(111);
var result = fs.readFileSync("2.txt", "utf-8");
console.log(result);
console.log(222);

总结:同步操作使用虽然简单,但是会影响性能,因此尽量使用异步方法,尤其是在工作过程中。

stream
stream是Node.js提供的又一个仅在服务区端可用的模块,目的是支持“流”这种数据结构。

什么是流?流是一种抽象的数据结构。想象水流,当在水管中流动时,就可以从某个地方(例如自来水厂)源源不断地到达另一个地方(比如你家的洗手池)。我们也可以把数据看成是数据流,比如你敲键盘的时候,就可以把每个字符依次连起来,看成字符流。这个流是从键盘输入到应用程序,实际上它还对应着一个名字:标准输入流(stdin)。

如果应用程序把字符一个一个输出到显示器上,这也可以看成是一个流,这个流也有名字:标准输出流(stdout)。流的特点是数据是有序的,而且必须依次读取,或者依次写入,不能像Array那样随机定位。

有些流用来读取数据,比如从文件读取数据时,可以打开一个文件流,然后从文件流中不断地读取数据。有些流用来写入数据,比如向文件写入数据时,只需要把数据不断地往文件流中写进去就可以了。

在Node.js中,流也是一个对象,我们只需要响应流的事件就可以了:data事件表示流的数据已经可以读取了,end事件表示这个流已经到末尾了,没有数据可以读取了,error事件表示出错了。

下面是一个从文件流读取文本内容的示例:

'use strict';

var fs = require('fs');

// 打开一个流:
var rs = fs.createReadStream('sample.txt', 'utf-8');

rs.on('data', function (chunk) {
    console.log('DATA:')
    console.log(chunk);
});

rs.on('end', function () {
    console.log('END');
});

rs.on('error', function (err) {
    console.log('ERROR: ' + err);
});

要注意,data事件可能会有多次,每次传递的chunk是流的一部分数据。

要以流的形式写入文件,只需要不断调用write()方法,最后以end()结束:

'use strict';

var fs = require('fs');

var ws1 = fs.createWriteStream('output1.txt', 'utf-8');
ws1.write('使用Stream写入文本数据...\n');
ws1.write('END.');
ws1.end();

var ws2 = fs.createWriteStream('output2.txt');
ws2.write(new Buffer('使用Stream写入二进制数据...\n', 'utf-8'));
ws2.write(new Buffer('END.', 'utf-8'));
ws2.end();


所有可以读取数据的流都继承自stream.Readable,所有可以写入的流都继承自stream.Writable。

pipe
就像可以把两个水管串成一个更长的水管一样,两个流也可以串起来。一个Readable流和一个Writable流串起来后,所有的数据自动从Readable流进入Writable流,这种操作叫pipe。

在Node.js中,Readable流有一个pipe()方法,就是用来干这件事的。

让我们用pipe()把一个文件流和另一个文件流串起来,这样源文件的所有数据就自动写入到目标文件里了,所以,这实际上是一个复制文件的程序:

'use strict';

var fs = require('fs');

var rs = fs.createReadStream('sample.txt');
var ws = fs.createWriteStream('copied.txt');

rs.pipe(ws);

默认情况下,当Readable流的数据读取完毕,end事件触发后,将自动关闭Writable流。如果我们不希望自动关闭Writable流,需要传入参数:

readable.pipe(writable, { end: false });
1
path模块
路径操作的问题
具体的说明可以参考 NodeJs学习.md

在读写文件的时候,文件路径可以写相对路径或者绝对路径

//data.txt是相对路径,读取当前目录下的data.txt, 相对路径相对的是指向node命令的路径
//如果node命令不是在当前目录下执行就会报错, 在当前执行node命令的目录下查找data.txt,找不到
fs.readFile("data.txt", "utf8", function(err, data) {
  if(err) {
    console.log("读取文件失败", err);
  }

  console.log(data);
});

相对路径:相对于执行node命令的路径

绝对路径:__dirname: 当前文件的目录,__filename: 当前文件的目录,包含文件名

path模块的常用方法
关于路径,在linux系统中,路径分隔符使用的是/,但是在windows系统中,路径使用的\

在我们拼写路径的时候会带来很多的麻烦,经常会出现windows下写的代码,在linux操作系统下执行不了,path模块就是为了解决这个问题而存在的。

常用方法:

path.join();//拼接路径

//windows系统下
> path.join("abc","def","gg", "index.html")
"abc\def\gg\a.html"

//linux系统下
> path.join("abc","def","gg", "index.html")
'abc/def/gg/index.html'

http模块
创建服务器步骤

// 移入http模块
const http = require('http')
// 调用创建http 服务器的方法
const server = http.createServe()
// 给服务器注册request事件监听,每次浏览器像服务器发送请求的时候都会被监听到
server.on('request', function(request, response){
    // request 浏览器请求的数据,包括请求方式method 请求的地址 url等
    // response 浏览器的响应,可以设置响应头、响应体、响应状态码
    const method = request.method
    const url = request.url
    
    // 设置响应的状态码
    response.StatusCode = 404
    // 设置响应的头
    response.setHeader('Content-Type', 'text/html');
    // 设置响应体内容,write可以调用多次
    response.write('hello world!')
    // 响应结束
    response.end()
    
    // 如果在end(content),这样的写法相当于是让write和end的合写
    response.end('hello world!')
})
// 给服务器设置监听,相当于启动服务器
server.listen(8888,function(){
    console.log('服务器启动成功')
})

// 简写方式

http.createServer((req,res) => {
    ....
}).listen(8888,() => {
    ....
})

详细说明

给服务器注册request事件,只要服务器接收到了客户端的请求,就会触发request事件
request事件有两个参数,request表示请求对象,可以获取所有与请求相关的信息,response是响应对象,可以获取所有与响应相关的信息。
服务器监听的端口范围为:1-65535之间,推荐使用3000以上的端口,因为3000以下的端口一般留给系统使用
response对象详解
常见的属性和方法:

res.write(data): 给浏览器发送请求体,可以调用多次,从而提供连续的请求体
res.end();   通知服务器,所有响应头和响应主体都已被发送,即服务器将其视为已完成。
res.end(data); 结束请求,并且响应一段内容,相当于res.write(data) + res.end()
res.statusCode: 响应的的状态码 200 404 500
res.statusMessage: 响应的状态信息, OK Not Found ,会根据statusCode自动设置。
res.setHeader(name, value); 设置响应头信息, 比如content-type
res.writeHead(statusCode, statusMessage, options); 设置响应头,同时可以设置状态码和状态信息。
1
2
3
4
5
6
7
注意:必须先设置响应头,才能设置响应。

实现静态WEB服务器
服务器响应首页
注意:浏览器中输入的URL地址,仅仅是一个标识,不与服务器中的目录一致。也就是说:返回什么内容是由服务端的逻辑决定
server.on('request', function(req, res) {
  var url = req.url
  if(url === '/') {
    fs.readFile('./index.html', function(err, data) {
      if(err) {
        return res.end('您访问的资源不存在~')
      }

      res.end(data)
    })
  }
})

根据根据不同url,响应不同文件
content-type设置-MIME类型
MIME(Multipurpose Internet Mail Extensions)多用途Internet邮件扩展类型 是一种表示文档性质和格式的标准化方式
浏览器通常使用MIME类型(而不是文件扩展名)来确定如何处理文档;因此服务器将正确的MIME类型附加到响应对象的头部是非常重要的
MIME类型的通用处理-mime模块
作用:获取文件的MIME类型
安装:npm i mime
var mime = require('mime')

// 获取路径对应的MIME类型
mime.getType('txt')                    // ⇨ 'text/plain'
// 根据MIME获取到文件后缀名
mime.getExtension('text/plain')        // ⇨ 'txt'
1
2
3
4
5
6
有了这个模块我们就可以把设置响应头的代码改写成下面

// mime 不仅可以只写一个后缀名,还可以通过url来解析出后缀名来,因此这里可以直接写url
response.setHeader('content-type',mime.getType(request.url))
1
2
npm - Node包管理工具
初始化包
npm init;    //这个命令用于初始化一个包,创建一个package.json文件,我们的项目都应该先执行npm init
npm init -y;  //快速的初始化一个包, 不能是一个中文名
1
2
安装包
npm install 包名;  //安装指定的包名的版本到项目中
npm install 包名@版本号;  //安装指定包的指定版本

npm i 包名; //简写

卸载包
npm uninstall 包名;  //卸载已经安装的包
1
清除缓存
npm cache clean -f // 如果npm安装失败了,可以用这个命令来清除缓存
1
package.json文件
package.json文件,包(项目)描述文件,用来管理组织一个包(项目),它是一个纯JSON格式的。

作用:描述当前项目(包)的信息,描述当前包(项目)的依赖项
如何生成:npm init或者npm init -y
作用
作为一个标准的包,必须要有package.json文件进行描述
一个项目的node_modules目录通常都会很大,不用拷贝node_modules目录,可以通过package.json文件配合npm install直接安装项目所有的依赖项
描述内容
{
  "name": "03-npm",  //描述了包的名字,不能有中文
  "version": "1.0.0",  //描述了包的的版本信息, x.y.z  如果只是修复bug,需要更新Z位。如果是新增了功能,但是向下兼容,需要更新Y位。如果有大变动,向下不兼容,需要更新X位。
  "description": "", //包的描述信息
  "main": "index.js", //入口文件(模块化加载规则的时候详细的讲)
  "scripts": {  //配置一些脚本,在vue的时候会用到,现在体会不到
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],  //关键字(方便搜索)
  "author": "",  //作者的信息
  "license": "ISC",  //许可证,开源协议
  "dependencies": {   //重要,项目的依赖, 方便代码的共享  通过 npm install可以直接安装所有的依赖项
    "bootstrap": "^3.3.7",
    "jquery": "^3.3.1"
  }
}

注意:一个合法的package.json,必须要有name和version两个属性

本地安装和全局安装
有两种方式用来安装 npm 包:本地安装和全局安装。选用哪种方式来安装,取决于你如何使用这个包。

全局安装:如果你想将其作为一个命令行工具,那么你应该将其安装到全局。这种安装方式后可以让你在任何目录下使用这个命令。比如less命令,webpack命令,hcc-md命令 。
本地安装:如果你自己的模块依赖于某个包,并通过 Node.js 的 require 加载,那么你应该选择本地安装,这种方式也是 npm install 命令的默认行为。
// 全局安装,会把npm包安装到C:\Users\HUCC\AppData\Roaming\npm目录下,作为命令行工具使用
npm install -g 包名;

//本地安装,会把npm包安装到当前项目的node_modules文件中,作为项目的依赖
npm install 包名;  

常见的命令行工具
nrm
nrm:npm registry manager(npm仓库地址管理工具)
安装:npm i -g nrm
# 带*表示当前正在使用的地址

# 查看仓库地址列表
nrm ls

# 切换仓库地址
nrm use taobao

nodemon 自动重启
作用:监视到js文件修改后,自动重启node程序
安装:npm i -g nodemon
使用:nodemon app.js 运行node程序
模块化(module)
基本概念
在nodejs中,应用由模块组成,nodejs中采用commonJS模块规范。

一个js文件就是一个模块
每个模块都是一个独立的作用域,在这个而文件中定义的变量、函数、对象都是私有的,对其他文件不可见。
node中模块分类
1 核心模块
由 node 本身提供,不需要单独安装(npm),可直接引入使用
2 第三方模块
由社区或个人提供,需要通过npm安装后使用
3 自定义模块
由我们自己创建,比如:tool.js 、 user.js
核心模块
fs:文件操作模块
http:网络操作模块
path:路径操作模块
url: 解析地址的模块
querystring: 解析参数字符串的模块
基本使用:1 先引入 2 再使用
// 引入模块
var fs = require('fs');
1
2
第三方模块
第三方模块是由 社区或个人 提供的
比如:mime模块/art-template/jquery…
基本使用:1 先通过npm下载 2 再引入 3 最后使用
用户自定义模块
由开发人员创建的模块(JS文件)
基本使用:1 创建模块 2 引入模块
注意:自定义模块的路径必须以./获取../开头
// 加载模块
require('./a')     // 推荐使用,省略.js后缀!

require('./a.js')
1
2
3
4
模块导入
/* 
  nodejs中模块分为3大类
    1. nodejs本身提供的核心模块   fs http path url querystring
      核心模块不需要安装,直接导入即可。
      核心模块的加载语法: const fs = require('fs')
    
    2. 第三方模块  mime art-template
      第三方模块: 必须先安装(npm install XXX)  才能导入
      第三方模块的加载语法: npm install XXX   const mime = require('mime')
    
    3. 自定义的模块 一个js文件 
      不需要安装  只需要自己创建一个js文件
      自定义模块的加载语法:  require('模块的路径')  模块不能是名字,必须是路径  ./ ../ .js后缀是可以省略

  require加载规则(以mime模块为例)
  1. 判断是否是路径, 如果是  就是自定义模块
  2. 如果是名字 判断是否是核心模块
  3. 如果是第三方模块  在当前目录找node_modules
  4. 在node_modules中查找mime文件夹
  5. 查找是否有package.json, 查看是否main属性
  6. 判断是否有main, 如果没有,默认查找index.js  index.json index.node
  7. 如果没有
  8. 如果找不到,就去上一层目录,一直找到根目录
  9, 如果还没有,就说明模块不存在
*/

模块导出
/* 
  1. 模块中定义的变量和函数都是私有的
  2. 任意的一个模块中, 都有自带一个属性 module (全局属性) module代表的就是当前的这个模块。
  3. module中有一个属性  exports ,这个exports属性是一个对象,代表的就是当前模块的导出 module.exports当前模块唯一能够被外界访问到的

*/
//通过module.exports对外导出一些值
module.exports = 值  只能导出一个值
module.exports = {}  可以把所有要导出的内容都放到一个新的对象中
module.export.xxx = 值
/* 
  在任意的模块中 module.exports表示该模块的导出
  为了我们方便导出, 每个模块中还提供了 exports  
  exports 初始状态下,和module.exports指向了同一个对象。

  注意点: 如果通过exports的方式来导出内容,只能给对象增加属性 不能替换这个对象
*/
// 我们真正到处的对象是module.exports指向的对象
exports = {} // 这样只是改了exports的指向,而module.exports的指向没有改变,所以这样是不对的
// 以下这种是允许的
exports.xxx = '值'

express与mysql
首先需要安装mysql模块

npm i mysql
1
基本使用
// 导入第三方包
const mysql = require('mysql')
// 创建连接
var connection = mysql.createConnection({
  // 本地
  host: 'localhost',
  user: 'root',
  password: 'root',
  // 数据库名称
  database: 'mydb',
  port: 3306
})

// 连接数据库
connection.connect()

// 执行sql语句
connection.query('select * from user where id = 8', (err, result) => {
  if (err) return console.log('查询失败', err)
  // result返回的是数组, 数组中是一个对象
  console.log(result)
})

// 关闭连接
connection.end()


查询语句
var name = 'zs'
// 使用?表示占位,可以防止sql注入
connect.query(`select * from user where name=?`, name, (err, result) => {
  if (err) return console.log('错误了', err)
  console.log(result)
})
1
2
3
4
5
6
插入语句
connect.query(
  'insert into user (name, age, gender, content) values (?, ?, ?, ?)',
  ['zs', 18, '男', '哈哈哈哈'],
  err => {
    if (err) return console.log('错误', err)
    console.log('添加成功了')
  }
)

// 方式2
connect.query(
  'insert into user set ?',
  {
    name: 'zs',
    age: 30,
    gender: '男',
    content: '哈哈哈'
  },
  (err, result) => {
    if (err) return console.log('错误', err)
    console.log('添加成功了', result)
  }
)


修改语句
connect.query(
  'update user set ? where id = ?',
  [
    {
      name: 'zs',
      age: 30,
      gender: '男',
      content: '哈哈哈'
    },
    10
  ],
  (err, result) => {
    if (err) return console.log('错误', err)
    console.log('添加成功了', result)
  }
)

删除语句
connect.query('delete from user where id = ?', 10, (err, result) => {
  if (err) return console.log('失败', err)
  console.log(result)
})
1
2
3
4
登录状态保持
http是无状态的,但是随着技术的发展,我们需要记住某些东西,但是因为http是无状态的,无法让服务器记住东西,因此就引入了cookie和session这两个东西,cookie用于浏览器端,session用于服务器端。

以用户登录为例:

当用户登录时,浏览器会给服务器发送请求,这时候服务器就会开辟一个空间用于存放session数据,并且会把生成的sessionId返回给浏览器,存放在浏览器的cookie中,之后浏览器在请求服务器的时候,就会去比对是否存在这个session。这样你的登录状态就已经保持下来了

cookie的特点

cookie大小只有4k
cookie每次请求的时候,都会自动携带
cookie可以设置过期时间
为了方便使用,我们可以使用express-session这个包,可以很方便使用session

express-session步骤:
1. 下载  npm i express-session
2. 导入  const session = require("express-session")
3. 使用session中间件
app.use(session({
    secret: 'itcast',
    // 设置浏览器端cookie的名字, 默认connect.sid
    name: 'itcast',
    resave: false,
    // 在浏览器和服务器连接的第一时间,分配session  给浏览器指定一个cookie
    saveUninitialized: true
}))
可以通过req.session访问到session
4. 登录成功,把登录成功的用户信息存储到 req.session.xxx中
5. 提供一个中间件,这个中间件在路由的前面,判断 req.session.xxx是否有值,有值,放走,没值,去登录,细节: 如果是/login 直接放走
6. 退出功能:  把req.session.xxx 清空即可


浏览器登录和退出
1. 登录做什么  把用户名和密码给服务器
2. 退出做什么, 1. 告诉服务器,要退出   2.(清缓存也行)

yarn和npm的说明
官网:https://yarn.bootcss.com/

Yarn是由Facebook、Google、Exponent 和 Tilde 联合推出了一个新的 JS 包管理工具 ,Yarn 是为了弥补 npm 的一些缺陷而出现的。

Yarn 缓存了每个下载过的包,所以再次使用时无需重复下载。
同时利用并行下载以最大化资源利用率,因此安装速度更快。
yarn的用法和npm的用法差不多
yarn命令
初始化一个新项目
yarn init
1
添加依赖包
yarn add 包名
1
升级依赖包
yarn upgrade 包名
1
移除依赖包
yarn remove 包名
1
安装项目的全部依赖
yarn
1
全局安装
yarn global add 包名
1
使用gulp自动化构建
官网:https://gulpjs.com/

中文文档:https://www.gulpjs.com.cn/

用自动化构建工具增强你的工作流程!

在开发过程中,有很多重复性的工作需要执行。

less转成css
对css代码压缩混淆
对js代码压缩混淆
写完代码后需要刷新浏览器
无法共用模版
gulp是前端开发过程中对代码进行构建的工具,是自动化项目的构建利器;她不仅能对网站资源进行优化,而且在开发过程中很多重复的任务能够使用正确的工具自动完成;使用她,我们不仅可以很愉快的编写代码,而且大大提高我们的工作效率。

gulp -----> grunt ------>webpack

环境安装
初始化项目
npm init -y
1
全局安装gulp
npm install gulp -g 
yarn global add gulp
1
2
作为项目的依赖进行安装
yarn add gulp --save-dev      或者    
yarn add gulp --save-dev
--save-dev 等同于 -D
如果这个依赖包只是在开发阶段需要用到,需要加-D
1
2
3
4
新建gulpfile.js文件
// 参数1: 任务名
// 参数2: 任务需要执行的内容
gulp.task('aa', function() {
  console.log('哈哈')
})
1
2
3
4
5
执行任务
gulp 任务名;

gulp; 如果不接任务名,那么会执行默认的 default任务
1
2
3
glup任务-文件拷贝-lib
文件拷贝使用到了gulp提供的几个核心方法
gulp.task: 定义任务

gulp.src() 读取文件

gulp.pipe() 把文件交给管道处理

gulp.dest() 输出文件到某个目录

gulp.task定义任务
gulp.src('./src/lib/**/*.*')把文件读取成一个文件流
gulp.pipe() 把文件流交给下一个流
gulp.dest('./dist/lib')输出文件
// 简单拷贝, 处理 lib文件夹, lib文件不需要做任何的处理,只需要拷贝到dist目录
// 任务需要加一个return, 表示任务完成
gulp.task('lib', function() {
  // 读取文件
  // gulp.src() 读取文件
  // gulp.pipe() 管道
  // gulp.dest() 放到哪儿
  return gulp.src('./src/lib/**/*.*').pipe(gulp.dest('./dist/lib'))
})
1
2
3
4
5
6
7
8
9
gulp任务-js代码压缩与混淆
gulp-uglify-es: 给js代码进行压缩,处理ES6的代码

gulp-rename: 重命名

安装依赖
yarn add gulp-uglify-es --save-dev 
1
配置任务
const uglify = require('gulp-uglify-es').default

gulp.task('js', function() {
  return gulp
    .src('./js/*.js')
    .pipe(uglify())
    .pipe(gulp.dest('./dist/js'))
})
1
2
3
4
5
6
7
8
安装重命名依赖
yarn add gulp-rename -D
1
重命名配置
task('js', function() {
  return src('./js/*.js')
    .pipe(dest('./dist/js'))
    .pipe(uglify())
    .pipe(
      rename({
        // 配置重命名的后缀名
        suffix: '.min'
      })
    )
    .pipe(dest('./dist/js'))
})
1
2
3
4
5
6
7
8
9
10
11
12
gulp任务-less处理
gulp-less: 把less变成css

gulp-rename: 重命名

gulp-minify-css: 压缩css代码

安装依赖包
yarn add gulp-less -D
1
less任务
// less任务
task('less', function() {
  return src('./less/*.less')
    .pipe(less())
    .pipe(
      rename({
        extname: '.css'
      })
    )
    .pipe(dest('./dist/css'))
})
1
2
3
4
5
6
7
8
9
10
11
安装css压缩处理包
yarn add gulp-minify-css -D
1
压缩css
// less任务
task('less', function() {
  return src('./less/*.less')
    .pipe(less())
    .pipe(
      rename({
        extname: '.css'
      })
    )
    .pipe(dest('./dist/css'))
    .pipe(minifycss())
    .pipe(
      rename({
        suffix: '.min'
      })
    )
    .pipe(dest('./dist/css'))
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
gulp任务-图片压缩
gulp-imagemin: 可以对图片进行压缩

gulp-cache: 图片压缩比较耗时的一个任务, 如果每次都对所有的图片进行重新压缩,比较浪费时间, 会缓存下来所有已经压缩过的图片

安装依赖
yarn add gulp-imagemin -D
1
压缩图片的任务
task('image', function() {
  return src('./img/*')
    .pipe(imagemin())
    .pipe(dest('./dist/img'))
})
1
2
3
4
5
安装gulp-cachae
yarn add  gulp-cache -D
1
压缩图片是比较耗时的,我们可以使用gulp-cache来缓存已经压缩过的图片
task('image', function() {
  return src('./img/*')
    .pipe(cache(imagemin()))
    .pipe(dest('./dist/img'))
})
1
2
3
4
5
参考资料:https://www.cnblogs.com/yuzhongwusan/p/5417090.html

gulp任务-处理html
gulp-minify-html: 压缩html文件

gulp-html-extend: 语句当前html去导入另一个html

压缩html
yarn add gulp-minify-html -D
1
使用
// 处理html
task('html', function() {
  return src('./src/*.html')
    .pipe(minifyHtml())
    .pipe(dest('./dist'))
})
1
2
3
4
5
6
导入html
yarn add gulp-html-extend -D
1
// 处理html
task('html', function() {
  return src('./src/*.html')
    .pipe(extender())
    .pipe(minifyHtml())
    .pipe(dest('./dist'))
})
1
2
3
4
5
6
7
在页面中,如何导入html

<!-- @@include ./template/header.html -->
1
gulp任务-清空任务
安装
yarn add del -D
1
配置任务
task('clean', function() {
  return del('./dist')
})
1
2
3
gulp-任务整合series
task('build', gulp.series('clean', 'html', 'less', 'js', 'image', 'lib'))
1
gulp任务-监听文件的变化
// 实现一个,修改代码,会自动执行任务
// 监听的任务,,,,,,做一件事件,当我们修改了对应的文件,需要执行对应的任务
// gulp.watch() 监视文件
task('watch', function() {
  // 参数1:监视的文件
  // 参数2: 对应的任务, 多个任务
  watch('./src/**/*.html', series('html'))
  watch('./src/less/*.less', series('less'))
  watch('./src/js/*.js', series('js'))
  watch('./src/lib/**/*.*', series('lib'))
  watch('./src/img/*.*', series('img'))
})

gulp任务-自动刷新
安装
yarn add gulp-connect -D
蓝蓝设计www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 平面设计服务

图片排版找不到灵感?送你17个实用技巧!

资深UI设计者

如果您想订阅本博客内容,每天自动发到您的邮箱中, 请点这里

排版的难处在于,我们不是根据已经设计好的版面来填充内容(套模板),而是要根据具体的内容来布局版面。比如版面中的图片有时候是一两张,有时候是十张八张,由于构成元素的不同,导致采用同样的构图、版式、形式往往是行不通的,所以葱爷今天的这篇文章就是要来分享,在不同情况下有哪些图片排版技巧。

单图排版

1. 平铺

即把图片铺满整个版面,这种处理方式多用于封面设计。

或者在内页中把某一半版平铺一张大图,另一半则排列文字或者小图。

平铺的图片比较有张力,有视觉重心的图片适合这么处理。下图平铺的效果就一般般。

还有一种情况是把图片当做背景,也可以采用平铺,如下图:

2. 四周留白

即图片要比版面小,并让其四周都留出空白。这里也分两种情况,一是图片位于版面正中央,图片周围的留白是对称的,这种效果类似于相框,常用于封面设计。

还有一种情况是图片周围的留白并不对称,如下图,留白较多的区域会用来排文字,常用于海报设计和画册内页设计。

3. 一条边出血

即把图片的一条边对齐边界,这么处理有点冲破束缚的意思,可以增加图片的想象力和版面的设计感。

4. 三条边出血

这么做会把版面分成两部分,一部分为色块,一部分为图片,在排版时我们还可以通过文字、色块或颜色把这两个部分联系起来。

5. 拆分

即把一张图片拆分成几份,然后隔开一些排列,这么做比单独放一张图片会更有设计感和趣味性,风景类图片适合这么处理。

6. 跨版

即在画册设计中,让图片同时占据两个版面。当在一个跨版中只有一张图片时,如果只把图片排在某一半版中,那么另一半版就容易单调,所以在这种情况下通常会使用跨版,而且图片放大后会更有张力,还能把左右两个版面关联起来。

双图排版

在画册的设计中,有时候我们应该把一 P 当成一个版面,而有时候则需要把一个跨版当成一个版面,这取决于具体的内容以及排版形式,所以图片的排版也要分成这两种情况来考虑。

1. 统一大小对齐排版

在一些作品集或产品画册中常用到此排法,视觉流程简单、清晰。

2. 统一大小错位排版

比对齐排版更有动感,且由于图片不多,所以也不会显得混乱。

3. 一大一小排版

这种排版对比鲜明、更有张弛,可以在一个跨版中使用,也可以是在某一 P 中使用。

还可以把其中的一张图片去底,这么组合起来更灵活,对比更强烈。

如果把整个跨版当成一个版面,那么可以把大的那张图进行跨版,小的那张图则不跨版。

或者把大图铺满一个 P,而小的图片和文字则排在另一个 P。

这两种排法都很大气且不失细腻。

多图排版

有时候一个版面内的图片会有很多,这种版面排起来会更有难度,常用的排版方式有以下 8 种。

1. 大小统一对齐排版

这种排法比较整洁,但缺少变化,适合用于目录页或者产品和人物介绍。

2. 大小不统一对齐排版

这种排法会比前一种更灵活一点。适合利用网格工具来辅助排版。

这种排版虽然没有统一图片的大小,但由于保持了严格的对齐关系,所以依然显得很整洁。

3. 图片与色块组合排版

图片与色块组合在一起排版既不会像只有图片那么单调,还可以利用色块排文字。不过注意色块的颜色不要太多,且颜色最好来自图片。

4. 错位排版

即把相连两张图片刻意错开,或者把图片与文字的位置互换,这么做可以有效打破图片完全对齐的单调,且由于有一定的规律,所以也不会对视觉流程造成太大影响。

5. 把图片拼成特定的形状

这种排法适合图片比较多的情况,这么做可以避免图片太多而显得混乱,而且因为拼成的形状要与设计需求相关,所以会显得更有创意。

6. 按照某一路径排版

这种排法跟前一种一样,适合数量较多的同类图片使用,可以避免图片排得太过分散,如果不统一图片的大小和方向,效果会比较活泼但不规范,适用于照片墙和儿童画册的排版。

如果统一图片的大小和方向,或者使它们呈渐变式的变化,这些图片还可以形成一定的节奏感,不仅不会乱,还很美观。

7. 一大多小排版

如果在版面中分开排列大小差不多的多张图片,那么该版面就会缺乏重点且没有张力,而如果把其中一张图片放大,与其他图片形成鲜明的大小对比,就可以有效解决这一问题。

8. 自由排版

即大小不需要统一、图片与图片之间也不一定要严格对齐,效果比较灵活,设计感较强,常用于杂志排版中。

这种排法有两点需要注意,一是图片不要排的太分散;二是最好要有大小对比。

去底图也很适合这么做,当然,在排版的时候也要有大小的区分,同时要注意图片与图片、图片与文字之间的轮廓要形成互补。

结语

版面中的图片数量有从一张到数十张不等,图片的排版方式也非常多,所以我没法一一列出,以上总结的 17 个技巧仅仅代表一些比较主流的方向,具体的变化还需要大家根据具体的内容和设计需求去做尝试和突破,希望这篇文章能给你一点帮助。

蓝蓝设计www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计  cs界面设计  ipad界面设计  包装设计  图标定制  用户体验 、交互设计、 网站建设 平面设计服务

vue路由加载页面时,数据返回慢的问题

seo达人

如果您想订阅本博客内容,每天自动发到您的邮箱中, 请点这里

场景:

vue路由加载页面时,数据返回慢的时候页面会有闪动的效果,数据加载前和加载后的区别。(特别是el-table表格数据)

思路:

路由前加载数据,等数据加载完再路由渲染页面

解决方案:

使用vue-router的 路由守卫 beforeRouteEnter,组件内直接定义以下路由导航守卫,和钩子函数的写法一样,下面列出三种路由守卫:

 beforeRouteEnter(to,from,next)0{
        // 在渲染该组件的对应路由被 confirm 前调用// 不!能!获取组件实例 `this`
        // 因为当守卫执行前,组件实例还没被创建
    } 复制代码
 beforeRouteUpdate(to,from,next){
        // 在当前路由改变,但是该组件被复用时调用
        // 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候,
        // 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
        // 可以访问组件实例 `this`
    } 复制代码
 beforeRouteLeave(to,from,next){
        // 导航离开该组件的对应路由时调用// 可以访问组件实例 `this`
    } 复制代码

vue-router详细,具体访问:导航守卫 数据获取

蓝蓝设计www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 平面设计服务


交互设计到底是什么?

用心设计

如果您想订阅本博客内容,每天自动发到您的邮箱中, 请点这里

 

当别人问你什么是交互设计时,你又一脸懵逼了。本篇文章就来好好聊聊什么是交互设计


工作了很多年,却依然说不出何为交互设计。一说道理,大家都懂,但是当别人问你什么是交互设计时,你又一脸懵逼了。为什么会这样呢?因为我们没有自己去总结,没有形成自己的知识库。

交互设计,它由IDEO的一位创始人比尔•莫格里奇在1984年一次设计会议上提出,他一开始给它命名为“软面(Soft Face)”,由于这个名字容易让人想起和当时流行的玩具“椰菜娃娃(Cabbage Patch doll)”,他后来把它更名为“Interaction Design”――交互设计。

首先,我们来看看权威方对交互设计的定义:

交互设计协会(The Interaction Design Association (IxDA))解释如下:

交互设计师以创造有用且实用的产品及服务为宗旨。以用户为中心作为设计的基本原理,交互设计的实际操作必须建立在对实际用户的了解之上:包括他们的目标、任务、体验、需求等等。以用户为中心的角度出发,同时努力平衡用户需求、商业发展目标和科技发展水平之间的关系,交互设计师为复杂的设计挑战提供解决方法,同时定义和发展新的交互产品和服务。

 

百度定义如下:

交互设计(英文Interaction Design, 缩写IXD),是定义、设计人造系统的行为的设计领域,它定义了两个或多个互动的个体之间交流的内容和结构,使之互相配合,共同达成某种目的。交互设计努力去创造和建立的是人与产品及服务之间有意义的关系,以“在充满社会复杂性的物质世界中嵌入信息技术”为中心。交互系统设计的目标可以从“可用性”和”用户体验“两个层面上进行分析,关注以人为本的用户需求。

 

唐纳德诺曼给出的定义:

重点关注人与技术的互动。目标是增强人们理解可以做什么,正在发生什么,以及已经发生了什么。交互设计借鉴了心理学、设计、艺术和情感等基本原则来保证用户得到积极的、愉悦的体验。

 

首先要知道什么是交互

交互,及沟通交流,发生互动关系。比如人和人之间的交互就比较好理解,最经典的一幕可以用孙悟空智斗金角大王、银角大王。金角大王说:孙行者,我叫你一声你敢答应吗?然后,金角大王就叫:孙行者。孙悟空回答:爷爷在此。就这样,孙悟空就被收进去了。这就是一个简单的交互。

再比如,我们每天上班,到公司和同事打招呼。你说:“早上好呀”,同事回答“早”。这也是一个常见的交流互动。

 



 

人和人之间的交互比较好理解,那人和机器呢?其实也是非常好理解的。我们都忘不了微信推出的摇一摇功能,打开摇一摇,摇动手机,就会出现“咔咔”的声音,然后加载,搜寻出一个和你同时在摇的人。其实,我们和任何机器之间的发生互动关系,都是属于交互。往更广的意义上说,如果失去了交互,地球将不再运转,将毫无生机。现在,智能时代已经到来,我们除了研究人和人、机器、产品、环境、服务、系统等之间的关系,还要研究机

器和人、机器、产品、环境、服务、系统之间的关系。

 



 

总之,当人(或机器)和事物(无论是人、机器、产品、服务、系统、环境等等)发生双向的信息交流和互动,就是一种交互行为。

 



 

其次,我们来聊聊设计

聊设计之前,我们要先说说艺术,原研哉老师对设计和艺术的描述非常精辟,下面就引用他的话。

 


 

艺术说到底是个人意愿对社会的一种表达,其起源带有非常个人化的性质,所以只有艺术家自己才知道其作品的来源。这种玄虚性使得艺术“很酷”。当然,解读艺术家生成的表达有多种方式。非艺术家通过对艺术的有趣阐释与艺术互动,欣赏之,评论之,在展览中对艺术进行再创作,或把艺术当做一种知识资源使用。

而设计,则基本上不是一种自我表达,它源于社会。设计的实质在于发现一个很多人都遇到的问题,然后试着去解决的过程。由于问题的根源在社会内部,除了能从设计师的视角看问题外,每个人都能理解解决问题的方案和过程。设计就是感染,因为其过程所创造的启发,是基于人类在普遍价值和精神上的共鸣。(来源,原研哉,设计中的设计)

通过上述的描述,我们不难发现,设计主要表现在发现问题–解决问题。而交互设计就是发现和解决人(或机器)和事物(包括人、机器、产品、服务、系统、环境等等)之间的互动关系问题。

所以说,交互设计的范围是非常广的,和各个学科都有涉及,我们可以通过下面的图来看看交互设计和各个领域之间的关系。

 



 

那交互设计主要是做什么工作呢?

作为交互设计师,也应该好好问问自己这个问题。通常,外界的人就认为我们就是画画原型,或者有时候画画UI,而我们通常就是这么做的,所以也不得不让人们这么想。而现在大多数交互设计就是指移动端、网页端的交互设计。

那么交互设计的核心竞争力是什么呢?对于很多公司来说,其实是没有交互设计这个岗位的,交互的工作就由产品经理和UI设计师各自分担了。现在产品经理基本都掌握了原型技能,而且产品经理通常在做需求移交的时候已经把交互表达的很清楚了。而且很多UI设计师能力较强一点的,在做设计的时候都会考虑到交互。如果交互设计师在公司就只做做原型,那么,你就会被取代。

那么交互设计的工作内容到底包含哪些呢?《用户体验要素》这本书很好的说明了这些内容。本书把用户体验要素分五个层级:战略层、范围层、结构层、框架层、表现层。不同层级,表示着你的不同能力,引用一下大众点评高级交互设计经理范怡的一张图,比较形象的描绘了交互设计的能力范畴和价值。

 



 

怎么样,看到这些是不是有一点点觉悟了呢。如果想做好一名交互设计师,就应该扩大自己的能力范围,提升自身价值。怎样做好交互设计呢?如何运用设计原理来做交互设计呢,我们下篇来聊聊唐纳德罗曼老师书里的交互设计6要素:示能、意符、约束、映射、反馈、概念模型。

 

原文地址:站酷
作者:Luyeelin

蓝蓝设计www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计

交互设计师自我成长的三个阶段

用心设计

如果您想订阅本博客内容,每天自动发到您的邮箱中, 请点这里

第一段:工具

设计师学习的第一阶段其实都是从工具开始的。这分为两种:
第一种是有形工具,比如PS、AI、Axure之类的软件;
另一种是无形工具,就是设计时用到的思维方式。
1、有形工具
先说第一种有形工具。
很多人在学习UI时很容易陷到工具的学习里去,觉得工具学的越多能力就越强。其实根本不是这么一回事,软件对交互来说是非常基础的一部分。
从UI视觉方面来考虑,PS就足够了,AI都显得略有多余,不需要其他软件。PS其实是一款非常强大的视觉软件,切图也比较方便,BAT等公司也是用的PS。
还有输出交互文档的工具,一种是PPT,一种是Axure,这两款软件就足够覆盖绝大多数交互文档了。当然还有其他软件,如果是快速迭代的原型直接在纸上画也可以。
交互需要快速沟通,你要拿着设计反复和其他人对接。要是搞了个很生僻的软件给别人,结果别人打不开,老板就会骂你。要记住自己是设计的一环,能快速传递自己的设计思路才是最重要的,不要搞一些生僻的软件、格式和字体,这都是门外汉干的事。
像AE、Flash面试时可能会给你加分,因为公司可能有一些高保真的动画展示要做,其实在真实工作中用到的机会非常少。
2、无形工具
第二种是无形的思考工具。设计思维其实最不好培养,说的残酷点,你可能看五年的书都出不来思维,最好能有人指点一下。

第二段:新产品、新思路

前沿的设计意识,是很多设计师容易忽略的。
这个怎么练呢?
每天一定要抽出三十分钟的时间看新产品和新思路,这是今天的互联网设计师必须要干的一件事。很多一线团队每天都会分享各种各样的新闻,百度有自己的分享机制,三星喜欢每个月让设计师找的交互、用研、技术信息,收集起来专门搞一个月报。
设计师有很多渠道可以看前沿信息,比如互联网一些事,爱范,36kr,瘾科技之类的网站。这种前沿意识非常重要,它决定了你能在二流公司还是一流公司,这是排在第二位的。
这个坚持三个月以后,自然而然就会飞跃,不需要怎么特意去学,这可不是培训可以得到的,养成一个好的习惯,每天看半小时其实就是最好的学习。

第三段:人——对人和需求的研究

工具和思维的问题比较好解决,最难解决的问题其实是“人”的问题。可能很多设计师一辈子都解决不了“人”的问题,而它对企业的影响又是最大的,交互设计最重要的就是解决“人”的问题。这一点甚至能决定一款千万级甚至上亿级产品的生死。要知道你的一切设计行为都是为商业负责的,所以前期对交互不甚了解,可以先从PS开始,后期就是“思维”和“人”,这两个东西是比较难的。


看看前辈是怎么说的:

交互设计目前发展得怎样,前景如何?
答:现在我们接触到的交互设计可能只局限在网页或者APP这种,交互设计是个很广泛的概念,前景肯定是有的。互联网是人和服务的对接,很多崭新的设计和商业模式一旦出来,那就是新的商机。

新手自学UI应该从何处入手?
答:视觉基础不好的就学PS去临摹,现在很多开源的信息,比如学UI网。如果临摹到一定程度,可以看一看dribbble,其实视觉非常好解决,思维的提升才困难。

学习交互设计需要掌握什么软件?
答:PPT和axure足够了,这两个东西都不需要学。随便来个人学两三天都能拿着软件画出漂亮的线框图,关键是你的线框图从哪里来、为什么要这么画。

交互设计师需要学习代码吗?
答:交互设计师不需要学代码。知道为什么企业招聘要求你们懂代码吗?因为很多企业希望你做了设计做前端,节省人力成本,正式公司都不会有这个要求。就算你觉得设计师应该学代码,建议你还是先把本行的设计能力学好。当两件事你都要做的时候意味着哪件事你都做不好,这是自我管理的问题。

交互需要手绘功底吗?
答:手绘功底?有或者没有都可以,交互不需要你造型能力多强,你只要能把逻辑关系画出来就行了,不需要搞什么素描阴影。你不是要做画家,朋友们,画家和设计师是有区别的。

内容来源网络,如有侵权请联系,承诺必定删除

蓝蓝设计www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计

常见的网页设计、文章设计错误

用心设计

如果您想订阅本博客内容,每天自动发到您的邮箱中, 请点这里


常见的网页设计、文章设计错误
本文来自阮一峰分享


 1.内容未按逻辑分成块

用户可以根据逻辑块轻易的获取信息。

具体做法为:将padding设置为120px-180px,同时不同的逻辑块使用不同的背景。


2.每个逻辑块的空白大小不一致 

对于每个逻辑块,需要设置同等大小且适宜的空白。否则网页看起来会很混乱,作者不会对每个逻辑块同等对待。



 

3.Padding不能设置过小,否则用户无法将内容分为逻辑块

 为了这点,插入大的空白(至少120px),以使内容按逻辑块分开。





4.背景图片和文字 应该对比鲜明

 


5.在一页中,样式过多

太多不同 的排版和样式将会使得页面不太专业以及难以阅读。

解决的方法是,以字体为例,设置一种字体,字体为正常或粗体(保证在两种不同样式之内)



 

6.背景颜色块过于狭窄




7. 在一个狭窄的列中,放入了过多的文字

这导致用户阅读需跳很多行,整体看起来也不行。推荐的做法为,减少列的数量,精炼文字。



蓝蓝设计www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计

这10个设计细节我不说你肯定不知道,但是看完你肯定会点赞!

资深UI设计者

如果您想订阅本博客内容,每天自动发到您的邮箱中, 请点这里

「设计」区别于「艺术」,在于艺术的主题是「我」,而设计的主题是「我们」。因为艺术多关乎于艺术家本身,而设计更多的是与产品和用户相关。所以最常被接受的观点是:设计的本质其实是找到解决问题的方法。

解决问题的最佳方式可以是最大限度地降低问题的负面影响甚至将其消除,也可能是让事物呈现出其应有的样子,此外再无更好的选择。就像 Facebook 的产品设计师 Ruthia He 提到的「Good design is both invisible and obvious」(好设计是无形也是显而易见的)。真正的好设计能给到用户的是用户心中对它所期待的样子,所以「设计」会符合常理到让人无从察觉。其实这其中的每一个体验流程、触点安排抑或是设计细节,都是设计师们的精心策划与用心。

为什么有时候在「朋友圈」发状态,文字信息会被折叠?

自从「微信」发布 7.0 的新版本后,部分朋友圈信息会被折叠的问题受到了广泛的讨论。腾讯的公关总监张军对此给出了官方解释:当用户在「微信」发表原创内容即直接输入文字,信息会折叠较少,文字会得到较大面积的展示;而当用户发布粘贴复制的内容时,文字只会显示一行,其他信息将会被折叠。团队做这样的信息呈现设计是为了鼓励用户多发原创内容,提升朋友圈的整体使用体验。

旅游达人都爱的Booking为什么这么好用?

从「Booking缤客」预定酒店住宿后,系统会自动下载订单信息至本地。这样,当用户到达目的地时无论当地网络状况如何(哪怕出现因网络原因无法正常访问 App 的情况),仍可毫无压力地随时查看订单详情页。毕竟作为一家定位于帮用户在网络上预订世界各地住宿的国际化平台,用户身处异国地区需要查看住宿信息的使用场景很普遍。这个看似不起眼的小细节,却从设计逻辑的层面优化提升了产品的易用性,让产品真正贴近用户真实的使用场景,变得更加好用。

B站是如何营造陪伴感,让用户看剧不孤单的?

Bilibili 网站的电脑端不仅会在主页显示在线总用户人数,还会在每个视频的播放页面显示当前正在观看此视频的人数。将原本后台统计的数据显性化呈现在用户可见的页面,一方面利用访问数据吸引用户的好奇心进行观看,另一方面也会给予用户陪伴感与归属感。当看到有这么多小伙伴与你同时在线观看同一部影片,虽然看不见彼此,但心理上会有陪伴感。一个人在家看剧仿佛也没那么孤单了。

如何保证用户的操作行为,始终位于手部舒适区之内?

多数产品在设计页面模态弹窗引导用户操作行为时,都会将操作控件放在固定的页面位置(一般居中或者处于页面底部)。但「抖音」的设计却让人眼前一亮:系统会自动检测用户进行操作时手指与屏幕的接触位置,并将模态弹窗的操控按钮显示在离用户手指最近的地方。随用户手部活动区域变化而灵活变更位置的模态弹窗设计,使用户在进行手势交互的过程中,操作动作能始终在手部的舒适区域内进行,是应对大屏时代十分友好的体验设计。

为了改善长文阅读体验,我们悄悄开发了这个小功能

不知道你有没有发现「优设」的文章浏览页面右下角隐藏有「文章目录」的按钮。将鼠标移到按钮上可以看到文章目录的小导航。小标题的罗列既清晰呈现了文章结构,帮助读者迅速理解文章;又能起到快速定位文章内容的作用,一键直达想看的内容区域。阅读篇幅较长的文章对于缺少耐心或讲究效率的同学而言,无疑是痛苦的。有了这个「目录」功能的设计,看长文时的舒适度与阅读效率都加倍了。

天天听「网易云音乐」的你,可能都没发现这个小秘密

我们天天听歌的「网易云音乐」,在有网与无网状态下打开应用的跳转页面其实是不同的。因为对用户而言,只有在有网络尤其是无线网络的场景里才会在线听歌,当播放器处于无网状态下能够播放的只有本地音乐资源。所以设计团队根据用户具体的使用场景,设定用户在有网状态下打开 App 会进入「发现」的音乐首页,而在无网情境里会直接跳转「我的音乐」页面。音乐首页便于用户发现音乐资讯与歌单推荐,在线听歌;而「我的音乐」方便直接打开「本地音乐」列表,离线听歌。区别化的页面跳转为用户缩短了行为路径,节省了操作步骤,让使用体验更贴合具体使用场景。

当你在「腾讯视频」追剧播放进程被电话打断…

在「腾讯视频」看视频如果遇到播放进程被其他任务打断暂停的情况(比如接电话或者分享),当再次回到播放界面时当前视频并不是接着刚刚的暂停处播放的,而是会从暂停处往前倒几秒播放。这就如同我们追剧时会看到很多片头都有回顾上一集剧情的道理。在这里,「腾讯视频」是想让用户通过复习倒回的几秒老画面回忆起之前的剧情,接着看新画面时就能更好地连接完整剧情,得到更加沉浸的观看体验了。同样拥有这个贴心设计的还有「优酷视频」。

「抖音」是怎样利用一个按钮的小心机,达到鼓励用户分享行为的目标的?

在「抖音」的内容推荐页面刷视频时,你会发现正常情况下页面右侧的「分享」按钮显示为代表分享含义的普通 icon。但如果你在当前页面停留时间较久观看该短视频第三遍时,系统会预判用户对此内容感兴趣并有潜在分享意愿,此时右侧的「分享」按钮就会变成闪动的朋友圈或微信图标了。差异化的图标变化设计突出了「分享」功能,一方面是对用户心理与动作的预判揣摩,另一方面也从潜意识里起到了鼓励用户分享行为的目的。做产品,想办法驱动用户分享行为真的很重要。

在社交产品发布状态收到CEO的点赞,是种什么样的心情?

玩「即刻」的同学应该都有发现,「即刻」CEO 瓦恁的账号在社区内活跃得像高仿。时常更新自己的状态分享生活日常以及常常点赞回复用户的举动,让瓦总收获了一批忠实粉丝。还有一个很有意思的互动是:所有用户在「即刻」发表的第一条状态都会被 CEO 瓦恁点赞,这对于新用户而言会得到很大的惊喜和虚荣心上的小满足吧。虽然新用户第一条点赞应该是代码小哥哥又调皮了,但 CEO 时不时地参与到用户的互动中,确实是不错的增加用户粘性的方式。

「支付宝」收款码的隐藏小心机

「支付宝」的收钱功能我们都很熟悉:打开自己的收款码设置好金额,再拿给对方扫码即为收钱。但你可能没注意,当手机处于向下倾斜的角度给对方进行展示时,界面会自动旋转二维码的朝向并将按钮置灰不可点击。这里的二维码旋转设计是为了方便对方看即扫码,而按钮置灰则是防止用户误操作点击到设置金额。从用户日常行为出发,解决扫码不便的麻烦,真是隐藏很深的小细节大体验。

蓝蓝设计www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计  cs界面设计  ipad界面设计  包装设计  图标定制  用户体验 、交互设计、 网站建设 平面设计服务

layui数据表格如何加工具栏?

seo达人

如果您想订阅本博客内容,每天自动发到您的邮箱中, 请点这里

实现的最终效果图(文末会贴出全部代码,方便参考) 



1, 将此行代码加在红线所在的位置

,{fixed: 'right', width: 150, align:'center', toolbar: '#toolbarDemo'}


2,在合适的HTML位置加入 

<script type="text/html" id="toolbarDemo">
    <div class="layui-btn-container">
        <button class="layui-btn layui-btn-sm" lay-event="update">编辑</button>
        <button class="layui-btn layui-btn-danger layui-btn-sm" lay-event="delete">删除</button>
    </div>
</script>
全部代码:

{include file="common/header"}

<div class="x-nav">
      <span class="layui-breadcrumb">
        <a href="">首页</a>
        <a href="">演示</a>
        <a>
          <cite>导航元素</cite></a>
      </span>
    <a class="layui-btn layui-btn-small" style="line-height:1.6em;margin-top:3px;float:right" href="javascript:location.replace(location.href);" title="刷新">
        <i class="layui-icon" style="line-height:30px">ဂ</i></a>
</div>

<table class="layui-hide" id="test" lay-size="sm" lay-filter="test"></table>

<script type="text/html" id="toolbarDemo">
    <div class="layui-btn-container">
        <button class="layui-btn layui-btn-sm" lay-event="update">编辑</button>
        <button class="layui-btn layui-btn-danger layui-btn-sm" lay-event="delete">删除</button>
    </div>
</script>

<script>
    layui.use('table', function(){
        var table = layui.table;

        table.render({
            elem: '#test'
            ,url:"{:url('admin/user/page')}"
            ,page: { //支持传入 laypage 组件的所有参数(某些参数除外,如:jump/elem) - 详见文档
                layout: ['limit', 'count', 'prev', 'page', 'next', 'skip'] //自定义分页布局
                //,curr: 5 //设定初始在第 5 页
                ,limit:10 //一页显示多少条
                ,limits:[5,10,15]//每页条数的选择项
                ,groups: 2 //只显示 2 个连续页码
                ,first: "首页" //不显示首页
                ,last: "尾页" //不显示尾页
            }
            ,cols: [[
                {field:'id', width:80, title: '代理ID', sort: true}
                ,{field:'username', width:100, title: '代理名称'}
                ,{field:'level', width:100, title: '代理级别'}
                ,{field:'email', width:80, title: '电子邮箱'}
                ,{field:'phone', width:280, title: '手机号'}
                ,{field:'agent_id', width:280, title: '上级代理ID'}
                ,{field:'status', width:280, title: '是否启用'}
                ,{field:'isAuth', width:280, title: '是否已经认证'}
                ,{field:'money', width:280, title: '金额'}
                ,{field:'created_time', width:280, title: '访问时间',sort: true}
                ,{fixed: 'right', width: 150, align:'center', toolbar: '#toolbarDemo'}
            ]]

        });


        //监听工具条
        table.on('tool(test)', function(obj){ //注:tool是工具条事件名,test是table原始容器的属性 lay-filter="对应的值"
            console.log(obj);
            var data = obj.data; //获得当前行数据
            var layEvent = obj.event; //获得 lay-event 对应的值(也可以是表头的 event 参数对应的值)
            var tr = obj.tr; //获得当前行 tr 的DOM对象

            if(layEvent === 'detail'){ //查看
                //do somehing
            } else if(layEvent === 'del'){ //删除
                layer.confirm('真的删除行么', function(index){
                    obj.del(); //删除对应行(tr)的DOM结构,并更新缓存
                    layer.close(index);
                    //向服务端发送删除指令
                });
            } else if(layEvent === 'edit'){ //编辑
                //do something

                //同步更新缓存对应的值
                obj.update({
                    username: '123'
                    ,title: 'xxx'
                });
            }
        });

    });

</script>
</body>
</html>

蓝蓝设计www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 平面设计服务

研究数十个热门 APP后,我来教你如何做好「设置头像」功能

资深UI设计者


如果您想订阅本博客内容,每天自动发到您的邮箱中, 请点这里

在这个看脸的时代,无论是真实社交,还是网络社交,甚至虚拟形象社交,都是「颜值即正义」。长得好看是一大优势,或者至少要满足彼此的审美才有进一步发展的可能。当然要想真正地完成社交目的,还是要看个人的社交能力。在进行网络社交时(兴趣社交除外),可谓「无头像,不社交」,毕竟跟陌生人搭讪的筛选成本太高,看头像照片是最直接快速的方式。据说,有好事者在三里屯注册了某一款陌生人社交软件,并将头像设置成了一个在卢浮宫的露背少女照片,在短短时间内,居然收到了 10000 多次点赞,头像的魔力可见一斑。


头像设置流程

头像设置流程一般包括头像选择、上传、裁剪、预览四个步骤,在用户界面展现时,部分步骤可合并或跳过,但至少要包括裁剪和预览。

1. 选择图片源

头像图片的来源包括本地图片、系统推荐头像、用户个人线上相册、即时拍摄等。同一产品在不同端可以支持不同的上传渠道,比如 PC 端摄像头拍摄质量不佳,而且台式机不一定配备,一般可以不做支持。

2. 上传条件限制

上传本地图片作为头像时,图片的格式、尺寸、文件大小规则应尽量放开限制,至少要支持 JPG、GIF、PNG、JPEG、BMP 等格式。随着手机拍摄照片的尺寸和大小越来越大,所以 5~6M 是一个比较合适的上限。关于服务器图片存储,应保留一张高清大图和多套不同尺寸的缩略图。

3. 裁剪处理

图片裁剪包括系统自动裁剪和用户手动裁剪。如果不支持手动裁剪,最好把系统自动裁剪和截取做了。京东商城 web 端就没有截取图片中央区域,而是直接挤压或拉伸图片,导致图片变形效果很差。手动裁剪时,一般要辅助缩放、旋转、镜像等功能。缩放时需注意极限值,否则会导致背景空白(如QQ空间),要做相应的填充处理。裁剪框最好加入辅助线(如九宫格、方圆)和遮罩,方便实时预览方形和圆形头像的效果。有时也会加入滤镜、贴纸等功能。

4. 效果预览

「所见即所得」是打造优良用户体验的诀窍之一,所以提供实时反馈和预览是必不可少的。比如裁剪得到的各种形状和尺寸的预览,滤镜效果实时渲染等。当然,实时性也和系统性能有关。

头像的常见展示形状包括方和圆,有时也有异形头像。关于头像形状的「方圆」论证可以参考微信和 QQ 设计师的官方回复。

同样作为腾讯的产品,为什么 QQ 的头像是圆的?而微信的头像是方的呢?

腾讯的回应如下:

相比方形,人的头像更接近圆形。圆形 QQ 头像能更突出头像弱化背景,也更鼓励用户使用真实自拍作为 QQ 头像。

QQ 作为平台会接入游戏和第三方应用内容,圆形 QQ 头像在这些方形、异形图标环境中提高辨识度,降低用户的认知门槛。

QQ 希望给用户传递乐在沟通,展现年轻个性的态度,圆形 QQ 头像更具灵动和活力,与之无缝衔接的头像挂件也为用户带来更个性化的搭配和丰富的自我展示。

因为照片本来是方的,方头像更符合用户习惯。

《为什么微信头像是方的?QQ头像是圆的?|你问鹅答》

还有百度小程序关于头像的规范可供参考:头像应保证清晰,头像的主体元素在方形或圆形参考线内,不遮挡关键信息,确保前端展现时能在圆形轮廓中展现完全。

设置头像的12种方式

1. 默认头像

为缩短注册流程,减少潜在用户流失,用户注册过程中一般不会强制用户设置头像。所以,为防止用户不去设置头像以及页面中头像加载不出来,系统会提供默认头像以便在相关位置展示。可以采用灰色头像,也可以采用基于企业吉祥物卡通形象设计的彩色头像(例如虾米、转转)。二者各有好处,灰色头像可以时常提醒用户去设置头像,彩色头像则可以丰富画面、增加趣味性。不过唯一的遗憾是一旦设置了新头像,改不回默认头像了,毕竟有的默认头像还是挺好看的。有的社区允许游客用户进行点赞、评论等操作,这时便会用到游客默认头像。当然,同一系统内,默认头像也可以不唯一,比如,根据用户性别、星座匹配头像,根据用户身份角色匹配头像(司机/乘客,招聘者/求职者),或者制作头像库为用户随机分配头像。

2. 系统推荐头像

让用户自己拍摄或找到一张自己满意的图片做头像,对有些用户而言其实是一件成本比较高的事情。如果用户群体足够大,图片质量难以保证,甚至内容监管又会带来新的问题,所以推荐一些优质头像供用户挑选,就成了一个很不错的辅助解决方案。QQ 很早就推出了类似功能,甚至成了会员服务的一部分。平安金管家 APP 也有类似功能,提供了四个商务风格的卡通头像供用户选择。

最近比较火的匿名社交APP Soul 也同样支持使用系统推荐头像,而且是只能使用系统头像,如下图所示,用户可以根据自己所设置的性别,头像风格选择心仪的头像。Soul 不允许用户上传其他照片作为头像,也是希望用户能抛开颜值,找到真正的灵魂伴侣。这些头像本身也体现了用户个体的审美情趣、价值观等。最近 Soul 新上线了「超萌捏脸功能」,下文会着重详细分析,不过捏脸而成的头像依然可以算是系统推荐头像,只是把头像拆解成了头发、脸、眉毛、眼睛、鼻子、嘴巴、衣服配饰等元素,然后再由用户自己排列组合。

3. 随机选择头像

前文也提到了随机头像,即系统会在用户注册成功后为其随机匹配头像,避免单一默认头像的沉闷,记忆中以前 GitHub 就是采用这种做法。另一种随机头像是指用户主动选择随机头像,获得相应的惊喜,比如哔哩哔哩就采用了这种做法。不过实在难以琢磨出这种类似「变脸」的玩法背后的设计逻辑。

4. 使用历史头像

在用户使用过一段产品之后,可能会积累大量的历史头像(主要是用户自主上传的,使用过的系统头像不记录在内)。QQ 就把用户的这些头像收集起来展示给用户,以便用户查看或重新选择,虽然用户重新使用的几率并不大,但不失为一种增进用户情感、提高用户粘性的做法,毕竟这里面满满都是青春的回忆,很容易给用户带来触动。

微信也有类似的做法,不过只能查看上一张头像。微信的设计哲学是不去刻意讨好用户,所以这里更多的是防止用户反悔,方便用户在最近使用的两张头像之间切换对比。马蜂窝的做法与 QQ 类似,不过增加了删除历史头像的功能(当前头像不可删除)。聊天宝(原子弹短信)有很多锤子的设计基因,锤子的设计师们推崇工匠精神,爱为用户创造小惊喜,所以聊天宝不能查看自己的历史头像,但却能查看好友的历史头像。不妨推测下背后的设计动机:现代人分分钟互相加个好友,但可能来不及备注,而人们对图像的记忆更准确、持久,所以看到头像可能就会很快地回忆起好友姓名、相识的场景等信息。

5. 文本头像

文本头像在商务类应用中比较常见,例如 OA。由于办公社交的社交属性并不是很强,更多在于及时通讯,所以图片头像并不是特别重要,并且文本头像中的字号更大,更容易辨识。要注意文本颜色和背景颜色的对比度,另外同一个应用中,文本和背景可以多做几个配色方案随机展示,以丰富视觉效果。此外还要注意文本的取值显示规则,下图是钉钉的部分页面截图,可以从中推测:

  • 汉字类:单个或两个汉字展示全部汉字,三个及以上汉字仅展示后两个汉字;
  • 英文类:一个单词时取前两个字母,两个及以上单词取前两个单词的首字母;
  • 数字类:单个或两个数字展示全部数字,三个及以上数字仅展示后两个数字。

6. 角色头像/匿名头像

相信很多人都玩过 QQ 的匿名聊天功能,然后就被管理员禁止了,它更像是一种娱乐性玩法。其实还有类似的做法,在游戏中较为常见,在角色确定前显示的是用户头像,角色确定后就显示角色头像。比如斗地主,地主身份确定前显示用户本身头像,确定后则显示角色头像,而且还会根据角色性别显示相应头像。

7. 动态视频头像

动态视频头像可以让用户跨越时间维度从多角度展示自己。依然以 QQ 为例,动态头像分两种,一种是 QQ 会员才可使用的动态头像,由系统推荐,用户自主选择;另一种是让用户自己拍摄录制。具体流程如下图,用户先录制视频,然后选择一帧作为静态头像,以便能在不支持展示动态头像的地方展示。这也是目前的一大趋势,不过如果好友列表的头像都在动也还挺吓人的。

8. 轮播头像

针对陌生人社交场景,如探探,头像更显得重要,左滑还是右滑就在刹那之间,点进去主页也根本不会下滑屏幕细看具体的兴趣、资料,所以就要尽量在首屏展示更多更大更清晰的照片,轮播图就是一种很好的形式。探探最多可设置 6 张图片或 6 段视频作为轮播头像。其实,轮播头像类似 QQ 照片墙的概念,不过自我展示意味更浓。

采用类似轮播头像做法的还有音遇 APP,虽说主张以歌会友,但谁都喜欢唱歌好听的小哥哥小姐姐还有高颜值。如下图,个人主页背景图即头像轮播。还有一些社交软件可以将个人系列头像设为私密,然后定向开放展示给需要的人。

9. 捏脸头像

ZEPETO(中文名:崽崽)的火爆刮起了一阵虚拟形象社交的风潮,虽然是三维形象的玩法,但和之前红极一时的脸萌并没有本质的区别,要想实现从工具到社交的转变,获取关系链才是王道。多闪和 Soul 动作也很快,已经上线了捏脸功能,虽然目前是二维的,但相信巨头们早已开始布局三维虚拟形象社交了。目前 ZEPETO 可编辑脸型,甚至可以进行简单的化妆。服装配饰则包括衣服、头饰、首饰等,且支持按上架时间、价格等排序。室内装饰则涵盖了地板、家具、摆件、乐器等等。手势主要是一些肢体动作库,动作效果十分连贯。可以说 ZEPETO 集成了用户对场景搭建+服饰搭配+颜值定义+炫酷动作的完美幻想,同时也扩充了人们对虚拟形象社交乃至电商新形态的想象空间。

目前市面上,尤其是游戏领域,不管画风是 Q萌,还是 3D,时尚亦或仙侠,人物建模及捏脸系统已经比较完善,且得到广泛应用。这里推荐一款叫做 IMVU 的 APP,它的人物画风、服饰质感比 ZEPETO 更加写实,更偏成人化,视角转换也更加流畅,支持俯视/仰视。不过,脸萌早已凉凉,美图的图片社交之路似乎完全和 ins 对不上标,所以 3D 虚拟形象社交的未来之路也未可知。

10. 头像挂件

头像挂件、等级徽章、认证标志也属于头像的一部分,不过需要结合付费会员、用户成长体系、认证规则进行讨论才有意义。

11. 使用第三方头像

使用第三方社交账号快速登录已经成为登录注册页面的标配,毕竟一个授权就解决了账号注册、头像及昵称设置等问题。这两天,吃瓜群众们又一次见证了「头腾大战」。多闪使用了用户的微信头像和昵称,可是并没有得到相应授权,因为之前的授权是给抖音的,当然现在也停止授权了。不管是不是抖音碰瓷,但微信/QQ 账户上的头像、昵称的权益归属确实是个问题。个人上传的头像还好说,如果用的是系统推荐头像,这些图片的版权是不是归属腾讯呢?用户使用第三方登录后,最好还是引导用户尽快绑定手机并设置完善其他资料。

12. 群组头像

这里以 QQ、微信和钉钉为例进行分析。微信群聊头像由群成员头像组合生成,在方框内嵌套群成员的方形头像,根据群成员的数量多少(1-9)进行相应排布,多于 9 人时显示前 9 人头像。另外,微信暂不支持设置图片为群头像。钉钉群与微信类似,不过外观上是圆形外框嵌套群成员的方形头像,显示数量也有所限制(最多显示前4个),但可以选择其他图片作为群组头像。QQ 群比较复杂些,可分为讨论组和群,虽然现在统称「群聊」,根据创建方式区分如下:选人创建(对应的是讨论组)和按分类创建(对应的是群)。讨论组也是不能设置头像的,是在圆形内嵌套群成员的圆形头像,最多可显示前 5 个成员的头像。而群头像由管理员设置,且可以查看历史头像、使用系统推荐头像等。另外还有 TIM,定位是对抗钉钉的办公软件,比 QQ 更轻量化,视觉风格也大不相同, TIM 中讨论组头像的展示就采用了类似钉钉的做法──圆形外边框+方形头像。

延伸一下,有人说微信重新定义了群的设计形态,更贴近用户自然使用方式:无需群ID,无需刻意创建群,随时拉人开聊,无需命名,默认不保存到通讯录,搜索群时可通过直接搜人实现等。

结语

本文列举分析了头像设置的相关设计思路和案例,对社交产品的头像设计大有裨益。在设计时,寻求相关设计参考是获取灵感和解决方案的有效方法,认真发现生活中的好设计,及时积累并总结,才能在关键时刻有高质量的输出。

蓝蓝设计www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计  cs界面设计  ipad界面设计  包装设计  图标定制  用户体验 、交互设计、 网站建设 平面设计服务


Echarts 动态更新散点图

seo达人

如果您想订阅本博客内容,每天自动发到您的邮箱中, 请点这里

 最近遇到一个作业,要求使用 Echarts 散点图,本来这个图是很容易的,官网上也有很多的教程。但是如果可以动态的更新 Echarts 散点图就更好了。我本身对 js 不感兴趣,经过不停的查找资料最终实现了这一功能。
我的项目是 Servlet + jsp + Echarts。先从 Servlet 入手,我们的项目需要传递的数值是 x 坐标和 y 坐标。我首先写了一个 JavaBean

julie.java

package JavaBean;

public class julei {
    public julei(double x, double y) {
        this.x = x;
        this.y = y;
    }
    double x;

    public double getX() {
        return x;
    }

    public void setX(double x) {
        this.x = x;
    }

    public double getY() {
        return y;
    }

    public void setY(double y) {
        this.y = y;
    }

    double y;

    @Override
    public String toString() {
        return "[" + this.x + "," + this.y + "]";
    }
}


Servlet中的代码,因为使用的是 json 来传递的数据,所以 json 相关的包还是少不了的。
BackServlet

package Servlet;

import JavaBean.Readtxt;
import JavaBean.julei;
import org.json.JSONArray;
import org.json.JSONObject;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@javax.servlet.annotation.WebServlet("/BackServlet")
public class BackServlet extends javax.servlet.http.HttpServlet {
    protected void doPost(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, IOException {



        List<julei> list = new ArrayList<>();
        try {
            list = Readtxt.out();//这是我们项目中的一个类,不重要。
        }catch (Exception e)
        {
            System.out.println(e.toString());
        }


        JSONArray jsonArray = new JSONArray(list);
        System.out.println(jsonArray.toString());
        //最重要的就是这一句,将数据发送给谁来申请的位置
        response.getWriter().write(jsonArray.toString());


    }

    protected void doGet(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, IOException {

    }
}


好了,现在到了最重要的前端方面了。
index.jsp
正常声明散点图,只要把data声明为空就好。

  var myChart = echarts.init(document.getElementById('man'));
          var option = {
            title : {
              text: '死亡分布图',
            },
            xAxis: {axisTick: {//决定是否显示坐标刻度
                alignWithLabel: true,
                show:true
              },},
            yAxis: {},
            series: [{
              symbolSize: 20,
              data: [],
              type: 'scatter'
            }]
          };
          myChart.setOption(option);

数据接收部分:

var num = [];
          var gao = new Array();
          $.ajax({
            type : "post",
            async : true, //异步请求(同步请求将会锁住浏览器,其他操作须等请求完成才可执行)
            url : "BackServlet", //请求发送到TestServlet
            data : {},
            dataType : "json", //返回数据形式为json

            //7.请求成功后接收数据name+num两组数据
            success : function(result) {
              //result为服务器返回的json对象
              if (result) {
                //8.取出数据存入数组

                for (var i = 0; i < result.length; i++) {

                  gao.push([result[i].x,result[i].y]);//这一句很重要,它将数据转化为了正确的格式。

                }

                myChart.hideLoading(); //隐藏加载动画

                //9.覆盖操作-根据数据加载数据图表
                myChart.setOption({
                  series : [ {
                    // 根据名字对应到相应的数据
                    data : gao//在这里对data进行赋值。
                  } ]
                });

              }

            },
            error : function(errorMsg) {
              //请求失败时执行该函数
              alert("图表请求数据失败!");
              myChart.hideLoading();
            }
          })




完毕

我把整个jsp都放上来了,但是里面的 css 还有 js 就不放了,重点是传数据的那一部分。

<%@ page language="java" contentType="text/html; charset=UTF-8"
         pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <title>LOL数据分析</title>
  <script src="https://cdn.bootcss.com/jquery/1.10.2/jquery.min.js"></script>
  <script type="text/javascript" src='js/echarts.js'></script>
  <link rel="stylesheet" href="css/jquery.fullPage.css">
  <link rel="stylesheet" href="css/style.css">
  <link rel="icon" href="https://jscdn.com.cn/highcharts/images/favicon.ico">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <script src="https://code.highcharts.com.cn/highcharts/highcharts.js"></script>
  <script src="https://code.highcharts.com.cn/highcharts/modules/exporting.js"></script>
  <script src="https://img.hcharts.cn/highcharts-plugins/highcharts-zh_CN.js"></script>
</head>

<body>
<div class="bgcolor">
  <div style="z-index:100;" id="dowebok">
    <!--第一屏-->

    <div class="section">
      <div class="ly-box01">
        <img class="ly-img01" src="img/logol.png" style="width:100%;height:100%">

      </div>
    </div>

 

    <!--第三屏-->

    <div class="section">
      <div class="timeline"></div>
      <div class="timepoint21"></div>
      <div class="ly-box11">
        <div id="man" style=" width: 600px;height: 500px;"></div>

        <script type="text/javascript">
          // 基于准备好的dom,初始化echarts实例
          var value=[];
          $.ajaxSettings.async=false;
          var myChart = echarts.init(document.getElementById('man'));
          var option = {
            title : {
              text: '死亡分布图',
            },
            xAxis: {axisTick: {//决定是否显示坐标刻度
                alignWithLabel: true,
                show:true
              },},
            yAxis: {},
            series: [{
              symbolSize: 20,
              data: [],
              type: 'scatter'
            }]
          };
          myChart.setOption(option);






          var num = [];
          var gao = new Array(4);
          $.ajax({
            type : "post",
            async : true, //异步请求(同步请求将会锁住浏览器,其他操作须等请求完成才可执行)
            url : "BackServlet", //请求发送到TestServlet
            data : {},
            dataType : "json", //返回数据形式为json

            //7.请求成功后接收数据name+num两组数据
            success : function(result) {
              //result为服务器返回的json对象
              if (result) {
                //8.取出数据存入数组

                for (var i = 0; i < result.length; i++) {
                  gao.push([result[i].x,result[i].y]);
                }

            //  document.write(gao);
                myChart.hideLoading(); //隐藏加载动画

                //9.覆盖操作-根据数据加载数据图表
                myChart.setOption({
                  series : [ {
                    // 根据名字对应到相应的数据
                    data : gao
                  } ]
                });

              }

            },
            error : function(errorMsg) {
              //请求失败时执行该函数
              alert("图表请求数据失败!");
              myChart.hideLoading();
            }
          })






        </script>
      </div>
      <div class="ly-triangle21"></div>
    </div>
  <!--试验-->

  <ul class="bg-bubbles">
    <li><img src="img/logol.png" style="width:100%;height:100%"></li>
    <li><img src="img/logol.png" style="width:100%;height:100%"></li>
    <li><img src="img/logol.png" style="width:100%;height:100%"></li>
    <li><img src="img/logol.png" style="width:100%;height:100%"></li>
    <li><img src="img/logol.png" style="width:100%;height:100%"></li>
    <li><img src="img/logol.png" style="width:100%;height:100%"></li>
    <li><img src="img/logol.png" style="width:100%;height:100%"></li>
    <li><img src="img/logol.png" style="width:100%;height:100%"></li>
    <li><img src="img/logol.png" style="width:100%;height:100%"></li>
    <li><img src="img/logol.png" style="width:100%;height:100%"></li>
  </ul>

</div>

<audio src="music/1.mp3" autoplay="autoplay" loop="loop" />
<script src="js/jquery-1.8.3.min.js"></script>
<script src="js/jquery.fullPage.min.js"></script>
<script src="js/diy.js"></script>
</body>
</html>
蓝蓝设计www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 平面设计服务

日历

链接

个人资料

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

存档