首页

汽车行业的UX启发-车载HMI的经验法则

ui设计分享达人




在网上找UX汽车相关的材料和文章是相当困难的。(学习君说:表示相当赞同:( )尽管有关移动和台式设备UX的信息太多,但要获得关于HMI(人机交互)原理的见识似乎要困难得多。为什么?


我的回答是,与为手持设备和计算机进行设计相比,这可能是一门利基学科,再加上汽车屏幕出现的时间不长。当然,车辆上的用户体验不仅仅是屏幕,只有旋钮和物理按钮时已经是用户体验了,但是在这种知识上也没有太多分享。



没有标准


但是,主要原因可能是缺乏标准化。如果您现在看一下市场,您会发现有太多不同的方法和解决方案(满足相同的需求),很难提出一套共享的规则。屏幕可以是横向或纵向屏幕,可以是直角或倾斜角度,可以是一个或2个或3个或更多,超宽或更大的正方形,仪表板上的高度或膝盖以下的高度,等等。与这种混乱相比,我们在手机上拥有的屏幕尺寸数量似乎是在开玩笑。



严格测试


另一个原因是所有车载系统都需要非常全面的测试。用户在可能致命的情况下与这些对象进行交互。因此,测试必须绝对优先。搞砸移动应用程序上的按钮的位置或大小可能会带来麻烦,但在汽车操作系统上这样做(我不是说“信息娱乐”,因为在这一点上,它是一个简化的术语)会造成生命损失。上面提到的缺乏标准化使得很难将先前测试的结果用于其他系统并在其他系统上重用。


但尽管如此,仍然存在一个人为因素组件,它使我们可以定义一组经验法则(或启发法)。这并不意味着他们可以跳过测试,但这是对所有对这个不断发展的行业感到好奇的UX设计人员(包括UI人员)的一些通用原则。



1.首选暗模式


各种研究表明,黑暗的UI在汽车环境中是最安全的选择。深色界面可减少干扰和眩光,但是,存在一个组件,从暗模式切换为亮模式可能有助于提高可读性,这就是导航图。在几乎所有导航系统中,地图都会自动从暗切换为亮,反之亦然。



Android Auto 



2.短文本,无段落


文字应略读,因此所有的号召性用语,菜单和所有文字通常都应保持最少。除非是在不运动的情况下阅读的文本,否则任何文本都不应排在两行或更多行上。



3.最小字体


眼睛到中央显示器的平均距离约为60厘米/ 24英寸。该数字只是根据市场上最常见的配置进行的平均测量,但是同样,由于没有适当的标准,因此该距离可能会有很大差异。


假定此措施为有效基准,则在运动情况下字体的最小尺寸为5.3 / 6毫米(不同的研究表明最佳做法略有不同)。考虑到1mm为6.299 dp(@ 160dpi),则文本应为34/38像素高,用于应该在行驶时读取的文本。



4.减少号召性用语


应该只有一个主要动作,而第二个动作则尽可能少。同样,我们希望用户快速浏览并一眼就能找到所需的内容。


(美国)美国国家公路交通安全管理局(NHTSA)指南指出,驾驶员应该能够在1.5秒的一系列扫视中完成一项任务,并且花在离开道路上的累积时间不超过12秒。



Apple CarPlay — phone call: 1 primary CTA 




5.导航,媒体和通话是主要功能


自从诞生以来,车载操作系统已超越了信息娱乐功能。通过镜像智能手机甚至系统内部的镜像,我们可以访问多种功能,例如消息传递,日历和提醒,流视频等等。但是,用户在使用这些系统时要寻找的主要功能是3:


  • 音乐/播客/有声读物

  • 导航

  • 拨打/接听电话


这三个主要功能在驾驶时应该比其他功能更醒目且易于使用。



6.文字上方的图标,但必须明显


图标优于文本标签,但图标的含义必须绝对清楚,不能解释误解。图标标签的字体大小可以小于第3点指示的最小字体大小。




Porsche Panamera UI 




7.高对比度


驾驶情况下的理想对比度至少应为7:1,因此绝大多数系统都将白色(或浅灰色)变成黑色(或深灰色)。

对于行驶中未使用/读取的组件,最小值应为4.5:1。



8.首选手势


旋钮和物理按钮的性能仍然优于GUI组件,这是由于其具有肌肉内存映射功能,触摸屏上的可视元素要求驾驶员每次查看屏幕。但是,数字接口的灵活性毋庸置疑,世界正在朝这个方向发展。尽管大多数(如果不是全部)现代触摸屏都支持各种类型的交互,例如您的常规平板电脑,但由于易于执行,因此它们是首选的:


  • 单点

  • 向左/向右/向上/向下滑动

  • 滚动(带有捕捉)


应避免使用其他更复杂的手势,例如触摸和按住,双击,捏合,多点触摸手势,或者在非运动情况下使用。

关于滚动的注意事项:在列表或卡片上自由滚动不是理想的选择。垂直和水平滚动动作均应具有捕捉效果,以始终将滚动项锁定在同一位置



Scroll with snapping on the left, free on the right 



非接触手势是许多OEM尝试的新事物。目前,这项技术似乎还远远不够完美,但是除此之外,在这种情况下使用的手势通常并没有真正令人难忘和自然。



9.语音不一定是所有互动的解决方案


虽然语音控制似乎是理想的选择,但根据研究,在某些情况下,精神工作量可能会超出预期。在VUI并不是真正的“对话式”的较早系统上,情况更是如此,诸如Google Assistant或Siri之类的现代助手对信息较长的字符串的理解程度更高,从而减少了用语表达命令的精力。


但是,我们应该考虑不能选择说话的情况,例如,当婴儿在后座上睡觉或某人有言语障碍时,并提供一种安全,可视/触觉的方式来执行所有动作。



10.考虑屏幕的可达性和可读性


与移动设备甚至与带有台式计算机和椅子的办公室设置不同,在汽车中,座椅相对于屏幕呈固定角度,屏幕也固定在适当的位置。因此,必须考虑屏幕的可达性及其可读性。考虑到左侧的驾驶员,屏幕右侧的元素将导致可读性和可访问性降低(当然,在方向盘位于右侧的汽车中会发生相反的情况)。





11.使用明确的能力


避免使用重影按钮,辅助功能应非常清晰可见。主要行动和次要行动均应清晰可辨



Tesla Model 3 UI 



12.安全性和可用性在美观性之前


当然,这也不意味着丑陋(不幸的是,那里有一些丑陋的车载体验)。但是,在为车载屏幕设计时,您必须考虑告别微妙的色调,细腻的对比度,笔触细腻的图标,浅色字体,细小的文字……


极简主义受到欢迎,但它是由更少的可见组件组成的极简主义




正如本文开头所述,这些原则只是经验法则,不能以任何方式跳过严格的测试。但是,如果您是第一次使用智能手机和计算机的UX来接触汽车的HMI,那么这可能是您开始着手涉足这一复杂学科的起点。


转自:站酷-NickM 

利用键盘控制小方块的移动

前端达人

原理

  1. 利用键盘控制移动,则需要了解onkeydown函数,表示某个按键被按下,可以以此绑定一个事件响应函数,当键盘被按下时候,触发此事件,进行移动
  2. keyCode 对于keypress 事件,该属性声明了被敲击的键生成的 Unicode 字符码。对于 keydown 和 keyup 事件,它指定了被敲击的键的虚拟键盘码。虚拟键盘码可能和使用的键盘的布局相关。 因此我们可以根据keycode返回的字符码来判断用户所按下的键,下面就是一个用于测试上下左右按键的js代码,经过我的测试之后,返回37 38 39 40;

    window.onload = function(){
                var box = document.getElementById("box");
                document.onkeydown = function(event){
                    event = event || window.event;
                    console.log(event.keyCode);
                }           
            };
    3



    3.方块的移动实际上就是坐标的改变,因此需要offsetLeft 和offsetTop 来获得当前方块的坐标,然后将坐标进行一定的更改,就可以实现移动的效果了,下面给出代码

    window.onload = function() {
                document.onkeydown = function(event) {
                    event = event || window.event;
                    //设置移动速度
                    var speed = 10;
                    //当ctrl和方向按键同时按下时,提升移动速度
                    if(event.ctrlKey) {
                        speed = 50;
                    }
                    //获取div
                    var box01 = document.getElementById("box01");
                    switch(event.keyCode) {
                        /*keyCode返回按下按键的编码
                         * 37 向左
                         * 38向上
                         * 39向右
                         * 40向下
                         */
                        case 37:
                            box01.style.left = box01.offsetLeft - speed + "px";
                            break;
                        case 39:
                            box01.style.left = box01.offsetLeft + speed + "px";
                            break;
                        case 38:
                            box01.style.top = box01.offsetTop - speed + "px";
                            break;
                        case 40:
                            box01.style.top = box01.offsetTop + speed + "px";
                            break;
    
                    }
                };
    
            };
    



    这样就可以简单实现方块的移动,但是此时我们会发现一个问题,当我们进行移动的时候,按住按键不松手,理论上方块应该直接平滑的进行移动,但实际上并非如此,第一下它会有一个小的停顿,这实际上是浏览器防止误触所设置的,因此我们需要对此进行优化
    解决方案

    这里我采用了定时器的做法来解决这个问题,因为控制移动的因素有两个,一个是控制方向,一个是控制速度,控制方向没有问题,因此我们需要改变速度
    setInterval(function(){},time);这是一个定时器,我们只需要在time时间内调用一次函数,就可以解决停顿的问题了
    下面附上修改后的完整代码


    <!DOCTYPE html>
    <html>
    
    <head>
        <meta charset="UTF-8">
        <title></title>
        <style type="text/css">
            #box01 {
                width: 100px;
                height: 100px;
                background-color: #008000;
                position: absolute;
            }
        </style>
        <script type="text/javascript">
            window.onload = function() {
    
                //获取div
                var box01 = document.getElementById("box01");
                //设置移动速度
                var speed = 10;
                //设置移动的方向
                var dir = 0;
    
                setInterval(function() {
                    switch(dir) {
                        /*keyCode返回按下按键的编码
                         * 37 向左
                         * 38向上
                         * 39向右
                         * 40向下
                         */
                        case 37:
                            box01.style.left = box01.offsetLeft - speed + "px";
                            break;
                        case 39:
                            box01.style.left = box01.offsetLeft + speed + "px";
                            break;
                        case 38:
                            box01.style.top = box01.offsetTop - speed + "px";
                            break;
                        case 40:
                            box01.style.top = box01.offsetTop + speed + "px";
                            break;
    
                    }
    
                }, 50)
    
                document.onkeydown = function(event) {
                    event = event || window.event;
    
                    //当ctrl和方向按键同时按下时,提升移动速度
                    if(event.ctrlKey) {
                        speed = 50;
                    } else {
                        speed = 10;
                    }
                    //使dir等于keycode的值
                    dir = event.keyCode;
    
                    //当鼠标松开时,停止移动         ---如果不写这一个会造成无法停止移动的效果
                    document.onkeyup = function() {
                        dir = 0;
                    };
    
                };
    
            };
        </script>
    </head>
    
    <body>
        <div id="box01"></div>
    </body>
    

</html>

————————————————

版权声明:本文为CSDN博主「loving-cat」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。

原文链接:https://blog.csdn.net/weixin_42878211/article/details/104558443



Vuex的一些用法

前端达人

vuex的基础

1,状态管理(共享)

缓存数据==>内存, 只要刷新页面,数据就丢了

订单,详情等,,,不适用vuex缓存数据



用于



非父子通信的问题

缓存后端数据,提高用户体验

注意:

vuex只能有一个store,

为了防止多人修改,我们切割成子store, 再合并成唯一一个大的store对象

模块写法

import Vue from 'vue'
import Vuex from 'vuex'
import cinema from './module/cinemaModule'
import tabbar from './module/tabbarshowModule'

Vue.use(Vuex)

const store = new Vuex.Store({
  state: {

  }, // "全局"状态
  mutations:{

  },//唯一修改状态的地方
  //异步处理
  actions:{
  },
  // 对上面的“全局状态”进行数据处理, 类似于vue中的计算属性
  getters:{
  },

  modules:{
    cinema,
    tabbar
  }
})
export default store

2,子模块的写法

const module = {
  namespaced:true, //命名空间
  state :{
    cinemaList:[]
  },
  actions:{
    store.commit("setCinemaList",res.data.data.cinemas) //支持传参
  },
  mutations:{
    setCinemaList(state,data){
      console.log("setCinemaList",data)
      state.cinemaList = data
    }
  },
  getters:{
    topDataList(state){
      //state形参s, vuex自动调用时候,传来值
      return state.cinemaList.slice(0,5)
    }
  }
}

export default module

3,为了防止页面刷新丢失数据,所以还得找到其他插件来帮忙

import createPersistedState from "vuex-persistedstate"; //在index.js页面加入这个插件

// 加入下面的代码
const store = new Vuex.Store({
  plugins: [createPersistedState({
    reducer(val){
      return {
        user: val.user
      }
    }
  })]


————————————————
版权声明:本文为CSDN博主「m0_46436313」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/m0_46436313/article/details/104572076

javascript设计模式九:中介者模式

前端达人

中介者对象践行了最少知识原则,指一个对象尽可能少的了解别的对象,从而尽量减少对象间耦合程度。这样各个对象只需关注自身实现逻辑,对象间的交互关系交由中介者对象来实现和维护。



需求背景:



手机购买页面,在购买流程中,可以选择手机的颜色及输入购买数量,同时页面有两个展示区域,分别向用户展示刚选择好的颜色和数量。还有一个按钮动态显示下一步的操作,我们需要查询该颜色手机对应的库存,如果库存数量少于这次购买的数量,按钮将被禁用并显示库存不足,反之按钮可以点击并显示放入购物车。

<!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>中介者模式 购买商品</title>
</head>
<body>
    选择颜色: 
    <select id="colorSelect">
        <option value="">请选择</option>
        <option value="red">红色</option>
        <option value="blue">蓝色</option>
    </select>

    输入购买数量:
    <input type="text" id="numberInput">

    您选择了颜色:<div id="colorInfo"></div><br>
    您输入了数量:<div id="numberInfo"></div><br>

    <button id="nextBtn" disabled>请选择手机颜色和购买数量</button>

</body>
<script>

// 最初级的写法
var colorSelect = document.getElementById('colorSelect'),
    numberInput = document.getElementById('numberInput'),
    colorInfo = document.getElementById('colorInfo'),
    numberInfo = document.getElementById('numberInfo'),
    nextBtn = document.getElementById('nextBtn');

var goods = {
    'red': 3,
    'blue': 6
}

colorSelect.onchange = function(){
    var color = this.value,
        number = numberInput.value,
        stock = goods[color]

    colorInfo.innerHTML = color;

    if(!color){
        nextBtn.disabled = true;
        nextBtn.innerHTML = '请选择手机颜色';
        return;
    }

    if( ( (number-0) | 0 ) !== number-0 ){      //用户输入的购买数量是否为正整数
        nextBtn.disabled = true;
        nextBtn.innerHTML = '请输入正确的购买数量';
        return;
    }

    if(number > stock){     //当前选择数量大于库存量
        nextBtn.disabled = true;
        nextBtn.innerHTML = '库存不足';
        return;
    }

    nextBtn.disabled = false;
    nextBtn.innerHTML = '放入购物车';
}

numberInput.oninput = function(){
    var color = colorSelect.value,
        number = this.value,
        stock = goods[color]

    colorInfo.innerHTML = color;

    if(!color){
        nextBtn.disabled = true;
        nextBtn.innerHTML = '请选择手机颜色';
        return;
    }

    if( ( (number-0) | 0 ) !== number-0 ){      //用户输入的购买数量是否为正整数
        nextBtn.disabled = true;
        nextBtn.innerHTML = '请输入正确的购买数量';
        return;
    }

    if(number > stock){     //当前选择数量大于库存量
        nextBtn.disabled = true;
        nextBtn.innerHTML = '库存不足';
        return;
    }

    nextBtn.disabled = false;
    nextBtn.innerHTML = '放入购物车';
}

</script>
</html>

在上个示例中,对象间联系高度耦合,只是两个输入框还好,但如果有多个的话,相互联系就非常复杂了,此时就要考虑用到中介者模式。

<!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>中介者模式 购买商品</title>
</head>
<body>
    选择颜色: 
    <select id="colorSelect">
        <option value="">请选择</option>
        <option value="red">红色</option>
        <option value="blue">蓝色</option>
    </select>

    选择内存: 
    <select id="memorySelect">
        <option value="">请选择</option>
        <option value="32G">32G</option>
        <option value="16G">16G</option>
    </select>

    输入购买数量:
    <input type="text" id="numberInput">

    您选择了颜色:<div id="colorInfo"></div><br>
    您选择了内存:<div id="memoryInfo"></div><br>
    您输入了数量:<div id="numberInfo"></div><br>

    <button id="nextBtn" disabled>请选择手机颜色、内存和购买数量</button>
</body>
<script>
    var goods = {
        'red|32G': 3,
        'red|16G': 0,
        'blue|32G': 1,
        'blue|16G': 6
    }

    //引入中介者
    var mediator = (function(){
        var colorSelect = document.getElementById('colorSelect'),
            memorySelect = document.getElementById('memorySelect'),
            numberInput = document.getElementById('numberInput'),
            colorInfo = document.getElementById('colorInfo'),
            memoryInfo = document.getElementById('memoryInfo'),
            numberInfo = document.getElementById('numberInfo'),
            nextBtn = document.getElementById('nextBtn');

        return {
            changed: function(obj){
                var color = colorSelect.value,
                    memory = memorySelect.value,
                    number = numberInput.value,
                    stock = goods[color + '|' + memory];

                if(obj == colorSelect){      //如果改变的是选择颜色下拉框
                    colorInfo.innerHTML = color;
                }else if(obj == memorySelect){
                    memoryInfo.innerHTML = memory;
                }else if(obj == numberInput){
                    numberInfo.innerHTML = number;
                }

                if(!color){
                    nextBtn.disabled = true;
                    nextBtn.innerHTML = '请选择手机颜色';
                    return;
                }

                if(!memory){
                    nextBtn.disabled = true;
                    nextBtn.innerHTML = '请选择手机内存';
                    return;
                }

                if(!number){
                    nextBtn.disabled = true;
                    nextBtn.innerHTML = '请填写手机数量';
                    return;
                }

                if( ( (number-0) | 0 ) !== number-0 ){      //用户输入的购买数量是否为正整数
                    nextBtn.disabled = true;
                    nextBtn.innerHTML = '请输入正确的购买数量';
                    return;
                }

                if(number > stock){     //当前选择数量大于库存量
                    nextBtn.disabled = true;
                    nextBtn.innerHTML = '库存不足';
                    return;
                }

                nextBtn.disabled = false;
                nextBtn.innerHTML = '放入购物车';
            }
        }
    })()

    colorSelect.onchange = function(){
        mediator.changed(this)
    }

    memorySelect.onchange = function(){
        mediator.changed(this)
    }

    numberInput.oninput = function(){
        mediator.changed(this)
    }

    //以后如果想要再增加选项,如手机CPU之类的,只需在中介者对象里加上相应配置即可。
</script>
</html>
在实际开发中,还是要注意选择利弊,中介者对象因为包含对象间交互的复杂性,所以维护成本可能也会较高。在实际开发中,最优目的还是要快速完成项目交付,而非过度设计和堆砌模式。有时对象间的耦合也是有必要的,只有当对象间复杂耦合确实已经导致调用与维护难以为继,才考虑用中介者模式。

————————————————
版权声明:本文为CSDN博主「一期一会」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_34832846/article/details/85989945

弹性布局(Flex)+骰子旋转实例^v^

前端达人

弹性布局(Flex)

随着移动互联网的发展,对于网页布局来说要求越来越高,而传统的布局方案对于实现特殊布局非常不方便,比如垂直居中。

2009年,W3C 提出了一种新的方案----Flex 布局,可以简便、完整、响应式地实现各种页面布局。目前,它已经得到了所有浏览器的支持,这意味着,现在就能很安全地使用这项功能。

下面是一些弹性布局的基本语法:

两部分:

1. 语法是添加到父容器上的
        display : flex;(弹性盒子的标志哦!!!)
        flex-direction: row; 布局的排列方向 (主轴排列方向)
             row 默认值,显示为行。方向为当前文档水平流方向,默认情况下是从左往右。
             row-reverse  显示为行。但方向和row属性值是反的
             column  显示为列
             column-reverse 显示为列。但方向和column属性值是反的
        flex-wrap : nowrap; 是否进行换行处理。
             nowrap; 默认值,不换行处理
             wrap; 换行处理
             wrap-reverse; 反向换行
        flex-flow : flex-direction flex-wrap 复合写法 (是有顺序的)。
        justify-content ; 属性决定了主轴方向上子项的对齐和分布方式。  
            flex-start : 子项都去起始位置对齐。
            flex-end : 子项都去结束位置对齐。
            center : 子项都去中心位置对齐。
            space-between : 表现为两端对齐。多余的空白间距在元素中间区域分配,两边没宽。 
            space-around : 边缘两侧的空白只有中间空白宽度一半即每个块都有左右间距。
            space-evenly :每个flex子项两侧空白间距完全相等。
        align-items : 每一行中的子元素上下对齐方式。
            stretch;默认值,flex子项拉伸
            flex-start;容器顶部对齐
            center;容器居中对齐
            flex-end;容器底部对齐
        align-content : 跟justify-content相反的操作。侧轴的对齐方式。(最少需要两行才能看出效果,因为他是多行的一个上下对齐方式)
            默认:多行下,有几行就会把容器划分为几部分,默认就是stretch拉伸的。
            值跟justify-content取值是相同的。

2. 语法是添加到子容器上的?
        order : 排序(值越大越后)
            0:默认值      eg:1234
            1:放在后面    eg:1342
            -2:放在前面   eg:2134
        flex-grow : 扩展 ( 想看到扩展的效果,必须有空隙 )
            0 : 默认值 , 不去扩展
            0.5:占空隙的一半
            1 : 去扩展 , 会把空白区域全部沾满
         ( 注:子元素会按照设置的比例值来分配空隙,如果比例值总和小于1,那么会有空隙,如果比例值总和大于等于1,那么就没有空隙。)
        flex-shrink : 收缩
            正常默认值是1
            0表示不收缩,.5收缩小一些,2收缩大一些。(大小是跟正常缩放1进行比较的)
        flex-basis : 跟flex-shrink/flex-grow很像。
            flex-shrink/flex-grow是设置一个比例值,flex-basis是设置一个具体值。
        flex : 一种复合写法
            flex-grow  flex-shrink  flex-basis
            flex:1;
                flex : 1 1 0    
            flex:0;
                flex : 0 1 0
        algin-self: 跟align-items操作很像,区别就是只是针对某一个子项。
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        *{margin: 0;padding: 0;}
        ul{list-style: none;}
        a{text-decoration: none;}
        img{display: block;}

        .box1{width: 150px;height: 150px;display: flex;border: 1px black solid;margin: 20px auto;border-radius: 10px;justify-content: center;align-items: center;}
        .box1 div{width: 30px;height: 30px;border-radius:50%;background: black;}

        .box2{width: 150px;height: 150px;display: flex;border: 1px black solid;margin: 20px auto;border-radius: 10px;align-items: center;justify-content: space-between;}
        .box2 div{width: 30px;height: 30px;border-radius:50%;background: black;margin: 10px;}
        .box2 div:nth-of-type(1){align-self: flex-start;}
        .box2 div:nth-of-type(2){align-self: flex-end;}

        .box3{width: 150px;height: 150px;display: flex;border: 1px black solid;margin: 20px auto;border-radius: 10px;align-items: center;justify-content: space-between;}
        .box3 div{width: 30px;height: 30px;border-radius:50%;background: black;margin: 10px;}
        .box3 div:nth-of-type(1){align-self: flex-start;}
        .box3 div:nth-of-type(3){align-self: flex-end;}

        .box4{width: 150px;height: 150px;border: 1px black solid;margin: 20px auto;border-radius: 10px;display: flex;flex-direction: column;}
        .box4 div{height: 50%;display: flex;flex-direction: row;justify-content: space-around;align-items: center;}
        .box4 div li{display: block; width: 30px;height: 30px;border-radius:50%;background: black;}

        .box5{width: 150px;height: 150px;border: 1px black solid;margin: 20px auto;border-radius: 10px;display: flex;flex-direction: column;}
        .box5 div{height: 50%;display: flex;flex-direction: row;justify-content: space-around;align-items: center;}
        .box5 div li{display: block; width: 30px;height: 30px;border-radius:50%;background: black;}

        .box6{width: 150px;height: 150px;border: 1px black solid;margin: 20px auto;border-radius: 10px;display: flex;flex-direction: column;}
        .box6 div{height: 50%;display: flex;flex-direction: row;justify-content: space-around;align-items: center;}
        .box6 div li{display: block; width: 30px;height: 30px;border-radius:50%;background: black;}

        #box{width: 400px;height: 400px;margin: 20px auto;border: 1px springgreen solid; 
        perspective: 500px;perspective-origin: right top;}
        #box .main{position: relative;width: 150px;height: 150px;margin: 125px;
        transform-style: preserve-3d;transition: 4s;transform-origin: center center -50px;}
        #box .main .box1{position: absolute;background:limegreen;left: 0;top: 0;
        width: 150px;height: 150px;}
        #box .main .box2{position: absolute;background:limegreen;left: 0;top: 0;
        width: 150px;height: 150px;left: 150px;transform-origin:left; transform:rotateY(90deg);}
        #box .main .box3{position: absolute;background:limegreen;left: 0;top: 0;
        width: 150px;height: 150px;left: -150px;transform-origin:right; transform:rotateY(-90deg);}
        #box .main .box4{position: absolute;background:limegreen;left: 0;top: 0;
        width: 150px;height: 150px;top: -150px;transform-origin:bottom; transform:rotateX(90deg);}
        #box .main .box5{position: absolute;background:limegreen;left: 0;top: 0;
        width: 150px;height: 150px;top: 150px;transform-origin:top; transform:rotateX(-90deg);}
        #box .main .box6{position: absolute;background:limegreen;left: 0;top: 0;
        width: 150px;height: 150px;transform:translateZ(-150px) rotateY(180deg);}

        #box:hover .main{transform:rotateY(360deg);}
    </style>
</head>
<body>
    <div id="box">
        <div class="main">
            <div class="box1">
                <div></div>
            </div>
            <div class="box2">
                <div></div>
                <div></div>
            </div>
            <div class="box3">
                <div></div>
                <div></div>
                <div></div>
            </div>
            <div class="box4">
                <div>
                    <li></li>
                    <li></li>
                </div>
                <div>
                    <li></li>
                    <li></li>
                </div>
            </div>
            <div class="box5">
                <div>
                    <li></li>
                    <li></li>
                </div>
                <div>
                    <li></li>
                </div>
                <div>
                    <li></li>
                    <li></li>
                </div>
            </div>
            <div class="box6">
                <div>
                    <li></li>
                    <li></li>
                </div>
                <div>
                    <li></li>
                    <li></li>
                </div>
                <div>
                    <li></li>
                    <li></li>
                </div>
            </div>
        </div>
    </div>
</body>
</html>
注:默认情况下,在弹性盒子中的子元素的左右排列的。 注: 水平是主轴的时候:默认情况下,当宽高不写的时候,宽度由内容决定,高度由父容器决定。 垂直是主轴的时候:默认情况下,当宽高不写的时候,宽度由父容器决定,高度由内容决定。 注:当子项的总宽度大于父容器的时候,会自动收缩的(弹性的优先级是大于自身固定大小的) 注:当子项的内容已经达到了父容器最小宽高的时候,就会出现溢出的现象。 注:弹性布局中用的频率比较多的语法: display : flex; flex-direction; justify-content; align-items; flex; 注:弹性布局的优势是做一维布局,网格布局的优势是做二维布局。

下面是弹性布局骰子案例代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        *{margin: 0;padding: 0;}
        ul{list-style: none;}
        a{text-decoration: none;}
        img{display: block;}

        .box1{width: 150px;height: 150px;display: flex;border: 1px black solid;margin: 20px auto;border-radius: 10px;justify-content: center;align-items: center;}
        .box1 div{width: 30px;height: 30px;border-radius:50%;background: black;}

        .box2{width: 150px;height: 150px;display: flex;border: 1px black solid;margin: 20px auto;border-radius: 10px;align-items: center;justify-content: space-between;}
        .box2 div{width: 30px;height: 30px;border-radius:50%;background: black;margin: 10px;}
        .box2 div:nth-of-type(1){align-self: flex-start;}
        .box2 div:nth-of-type(2){align-self: flex-end;}

        .box3{width: 150px;height: 150px;display: flex;border: 1px black solid;margin: 20px auto;border-radius: 10px;align-items: center;justify-content: space-between;}
        .box3 div{width: 30px;height: 30px;border-radius:50%;background: black;margin: 10px;}
        .box3 div:nth-of-type(1){align-self: flex-start;}
        .box3 div:nth-of-type(3){align-self: flex-end;}

        .box4{width: 150px;height: 150px;border: 1px black solid;margin: 20px auto;border-radius: 10px;display: flex;flex-direction: column;}
        .box4 div{height: 50%;display: flex;flex-direction: row;justify-content: space-around;align-items: center;}
        .box4 div li{display: block; width: 30px;height: 30px;border-radius:50%;background: black;}

        .box5{width: 150px;height: 150px;border: 1px black solid;margin: 20px auto;border-radius: 10px;display: flex;flex-direction: column;}
        .box5 div{height: 50%;display: flex;flex-direction: row;justify-content: space-around;align-items: center;}
        .box5 div li{display: block; width: 30px;height: 30px;border-radius:50%;background: black;}

        .box6{width: 150px;height: 150px;border: 1px black solid;margin: 20px auto;border-radius: 10px;display: flex;flex-direction: column;}
        .box6 div{height: 50%;display: flex;flex-direction: row;justify-content: space-around;align-items: center;}
        .box6 div li{display: block; width: 30px;height: 30px;border-radius:50%;background: black;}

        #box{width: 400px;height: 400px;margin: 20px auto;border: 1px springgreen solid; 
        perspective: 500px;perspective-origin: right top;}
        #box .main{position: relative;width: 150px;height: 150px;margin: 125px;
        transform-style: preserve-3d;transition: 4s;transform-origin: center center -50px;}
        #box .main .box1{position: absolute;background:limegreen;left: 0;top: 0;
        width: 150px;height: 150px;}
        #box .main .box2{position: absolute;background:limegreen;left: 0;top: 0;
        width: 150px;height: 150px;left: 150px;transform-origin:left; transform:rotateY(90deg);}
        #box .main .box3{position: absolute;background:limegreen;left: 0;top: 0;
        width: 150px;height: 150px;left: -150px;transform-origin:right; transform:rotateY(-90deg);}
        #box .main .box4{position: absolute;background:limegreen;left: 0;top: 0;
        width: 150px;height: 150px;top: -150px;transform-origin:bottom; transform:rotateX(90deg);}
        #box .main .box5{position: absolute;background:limegreen;left: 0;top: 0;
        width: 150px;height: 150px;top: 150px;transform-origin:top; transform:rotateX(-90deg);}
        #box .main .box6{position: absolute;background:limegreen;left: 0;top: 0;
        width: 150px;height: 150px;transform:translateZ(-150px) rotateY(180deg);}

        #box:hover .main{transform:rotateY(360deg);}
    </style>
</head>
<body>
    <div id="box">
        <div class="main">
            <div class="box1">
                <div></div>
            </div>
            <div class="box2">
                <div></div>
                <div></div>
            </div>
            <div class="box3">
                <div></div>
                <div></div>
                <div></div>
            </div>
            <div class="box4">
                <div>
                    <li></li>
                    <li></li>
                </div>
                <div>
                    <li></li>
                    <li></li>
                </div>
            </div>
            <div class="box5">
                <div>
                    <li></li>
                    <li></li>
                </div>
                <div>
                    <li></li>
                </div>
                <div>
                    <li></li>
                    <li></li>
                </div>
            </div>
            <div class="box6">
                <div>
                    <li></li>
                    <li></li>
                </div>
                <div>
                    <li></li>
                    <li></li>
                </div>
                <div>
                    <li></li>
                    <li></li>
                </div>
            </div>
        </div>
    </div>
</body>
</html>

实际效果:
20200229132935355.png


————————————————
版权声明:本文为CSDN博主「GLINLIND」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/GLINLIND/article/details/104572530



关于javascript跳转与返回和刷新页面

前端达人

javascript中window.open()与window.location.href的区别

window.open(‘index.html’) 表示新增一个窗口打开 index.html 这个页面,并不刷新

location.href(‘index.html’) 表示在当前窗口重定向到新页面,打开并刷新 index.html 这个页面



window.location 是 window 对象的属性,用来替换当前页,也就是重新定位当前页

而window.open 是 window 对象的方法,是用来打开一个新窗口的函数



// 打开新页面
    // 注意:有些浏览器的安全设置会将window.open()屏蔽,例如避免弹出广告窗
    window.open('./index.html');

    // 在原窗口打开新页面
    window.location.href="./index.html";

    

window.open()详解

window.open ('page.html', 'newwindow', 'height=100, width=400, 
top=0, left=0, toolbar=no, menubar=no, scrollbars=no, resizable=no,location=n o, status=no')

参数解释: 三个参数
 window.open 弹出新窗口的命令;
 ‘page.html’ 弹出窗口的文件名;
 ‘newPage’ 弹出窗口的名字(不是文件名),非必须,可用空’'代替;
 height=100 窗口高度;
 width=400 窗口宽度;
 top=0 窗口距离屏幕上方的象素值;
 left=0 窗口距离屏幕左侧的象素值;
 toolbar=no 是否显示工具栏,yes为显示;
 menubar=no 是否显示菜单栏,yes为显示;
 scrollbars=no 是否显示滚动栏,yes为显示;
 resizable=no 是否允许改变窗口大小,yes为允许;
 location=no 是否显示地址栏,yes为允许;
 status=no 是否显示状态栏内的信息(通常是文件已经打开),yes为允许;

常用的js返回与刷新页面
在此用a标签举例



网页炫酷背景

前端达人

前言:

做网页项目时想要背景是动态的,推荐两个我觉得比较可以的js动态背景。



随鼠标的移动而移动的线条,具体效果看图:

点击查看原图




你焦点在哪,那么那里的线条就会汇聚到你的焦点处。

用法:将js声明到body内即可,我是放置在body底部的

<script type="text/javascript" src="https://cdn.bootcss.com/canvas-nest.js/1.0.1/canvas-nest.min.js"&gt;&lt;/script&gt;

1

可以鼠标点击产生字的,如图:

点击查看原图

用法和第一个类似,不过在这个js文件前得先引入jquery:


<script src="https://cdn.jsdelivr.net/npm/jquery@3.2/dist/jquery.min.js"></script>
<script type="text/javascript">
            /* 鼠标 */
            var a_idx = 0;
            jQuery(document)
                    .ready(
                            function($) {
                                $("body")
                                        .click(
                                                function(e) {
                                                    var a = new Array("@健身",
                                                            "@学习", "@机车",
                                                            "@摄影", "@自由",
                                                            "@考研", "@自律",
                                                            "@独立", "@厨艺",
                                                            "@橘子", "@交友",
                                                            "@爱媳妇", "@爱家人");
                                                    var $i = $("<span></span>")
                                                            .text(a[a_idx]);
                                                    a_idx = (a_idx + 1)
                                                            % a.length;
                                                    var x = e.pageX, y = e.pageY;
                                                    $i
                                                            .css({
                                                                "z-index" : 999999999999999999999999999999999999999999999999999999999999999999999,
                                                                "top" : y - 20,
                                                                "left" : x,
                                                                "position" : "absolute",
                                                                "font-weight" : "bold",
                                                                "color" : "rgb("
                                                                        + ~~(255 * Math
                                                                                .random())
                                                                        + ","
                                                                        + ~~(255 * Math
                                                                                .random())
                                                                        + ","
                                                                        + ~~(255 * Math
                                                                                .random())
                                                                        + ")"
                                                            });
                                                    $("body").append($i);
                                                    $i.animate({
                                                        "top" : y - 180,
                                                        "opacity" : 0
                                                    }, 1500, function() {
                                                        $i.remove();
                                                    });
                                                });
                            });
        </script>


这里使用的是cdn形式的jquery即不用将jq放入本地文件再引入,直接访问网络上的jq即可,还有就是点击产生的字可以自行修改。

————————————————
版权声明:本文为CSDN博主「helllolsy」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/CodingNO1/article/details/104572143

html+css实现自定义图片上传按钮

前端达人




20190107095942123.png


可以自定义一个file选择文件的按钮:

思路为:
用定位将自定义的按钮遮住原来的选择文件按钮,
再让点击自定义按钮时触发原来的选择文件按钮的事件即可
(对此,label可实现)

eg:
html:

20190107105857285.png


css样式:


20190107105950752.png




20190107104448323.png

20190107104113359.png


结果图:

20190107100131675.png


点一下,就可以弹出选择文件的文件夹啦!


【Web前端开发】第二课、HTML基础之HTML概述

前端达人

文章目录

一、HTML的概述

  1. 什么是HTML?
  2. HTML的标签、元素、属性
  3. 标签、元素
  4. 标签、属性

    附:补充上一节课网站和网页的笔记:

    附:img标签的详细介绍

    一、HTML的概述
  5. 什么是HTML?

    HTML指的是超文本标记语言(Hyper Text Markup Language)

    HTML 不是一种编程语言,而是一种标记语言 (markup language)

    标记语言是一套标记标签 (markup tag)

    HTML 使用标记标签来描述网页

    HTML不区分大小写
  6. HTML的标签、元素、属性
  7. 标签、元素

    由尖括号包围,比如 <title>

    通常是成对出现的

    <title>百度一下,你就知道</title>



    其中,<title> 为 开始标签

    中间的 “百度一下,你就知道” 为内容

    </title>为结束标签, 我们可以清楚的观察到,标签结束是有 “/”。

    则 标签和内容,构成了网页的元素。



    标签的嵌套关系,如下列例子,你品

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

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


    标签的嵌套缩进

    20200228080404388.png



    如图所示<html>为外层标签,称为父元素,<head>和<body>为内层标签,称为子元素。其中<head>与<body>又互称为兄弟元素

    <!DOCTYPE html>



    声明不是 HTML 标签;它是指示 web 浏览器关于页面使用哪个 HTML 版本进行编写的指令。

    声明必须是 HTML 文档的第一行,位于 <html> 标签之前。

    <!DOCTYPE> 声明没有结束标签。

    <!DOCTYPE> 声明对大小写不敏感。

    在 HTML 4.01 中有三种 <!DOCTYPE> 声明。在 HTML5 中只有一种:<!doctype html>

    我们学习的是HTML5,所以我们不过多对HTML4的声明做过多解释。



    如果上述对<!doctype html>的概述不清楚的话,

    那记住以下两点即可,1. 不分大小写,2.在HTML的网页<html>标签之前加上<!doctype html>就可以啦。

    20200228083557474.png





    图示为 HTML DOM树,DOM:Document Object Model(文档对象模型)


    2. 标签、属性

    20200228084133219.png





    一个标签可能有多个属性,属性先后与顺序无关

    “=” 为赋值符号

    属性与属性之间用空格隔开

    附:补充上一节课网站和网页的笔记:

    HTML网页的编码为 utf-8

    网站可以理解成一个文件夹,而网页就是一个个的文件

    网页的文件后缀常见的有:htm、html、jsp、php、asp

    网站的文件结构通常包含 images文件夹,css文件夹,js文件夹,

    一个简单的网页,的文件目录通常由 images、css、js,作用顾名思义,就是存放相对应的文件资源

    附:img标签的详细介绍

    <img> 标签有两个必需的属性:src 和 alt。

    注释:从技术上来说,图像并不会插入到HTML页面中去,而是通过 src的值(URL) 链接到HTML页面上的,<img>标签的作用是为被引用的图像创建占位符。

    点击查看原图

    点击查看原图

    <img>标签常用的属性有src、alt、width、height、title

    src和alt为 img 标签的必需元素。



    话不多说,看图,为你们讲解代码。





    看网站的演示图和代码图,想必大家都很清楚了吧。

    (为了更直观的看到效果,我写了div和div的样式,1px粗的红色实线边框,这里的代码以后再具体详解)



    title和alt 的区别别,体现在 第 11 行和第 14 行,想必大家就能看出来了吧

    i. alt 属性是在图片不能正常显示时出现的文本提示。

    ii. title 属性是在鼠标在移动到元素上的文本提示。

    width和height的作用,用来规定图像的宽度和高度,单位为 像素(px)

    src路径,由于我的文件夹结构为 index.html文件和 images 文件夹。

    所以 src 的路径为 src="images/图片.后缀",即src="URL"

    URL即(Uniform Resource Locator,统一资源定位符,在WWW上,每一信息资源都有统一的且在网上唯一的地址。

    简单的理解URL,就是网址,地址



    如果图片路径引用错误,都会导致网页中的图片无法正常显示! 如,第 14 行和第 20 行代码。

    以上为img标签的常见用法。在我们写网页的时候,建议img写上 src、alt、width、height这四个属性,是否需要 title 具体看网站的功能。



    以上就是,第二课、Web前端开发之HTML基础的全部内容了,感谢阅读

    ————————————————

    版权声明:本文为CSDN博主「MineChen」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。

    原文链接:https://blog.csdn.net/MineSu/article/details/104549536

vue框架渐进性的理解和mvvm模式的理解

前端达人

引言

现在市场很多前端开发的招聘岗位都或多或少的要求你要掌握vue,可以说vue在国内是非常的火爆的,下面我给大家介绍一下vue框架吧!

vue是渐进式框架


201806191038393.png


vue的核心是一个视图模板引擎,但是这并不能说明vue不是一个框架,如上图所示在声明式渲染(视图模板)基础上,vue可以添加组件系统component,vue-router客户端路由,vuex的状态管理,vue-cli构建工具来构建一个完整的框架,更重要的是这些功能相互独立,你可以任意选用你项目需要的部件,不一定非要全部整合在一起(就像是vuex它是一个很好的可以管理组件之间共享状态的部件,但非必须在你的每一个项目中使用它,如果说你的项目相对简单,组件之间的通信相对简单你完全可以不使用它),可以看到渐进式,其实就是vue的使用方式,同时也能看到vue的设计理念
vue是mvvm模式
为什么说vue是mvvm模式呢?这个大家首先要知道mvvm是什么。mvvm是Model-View-ViewModel的简写,即模型视图视图模型。模型是指后端传过来的数据,视图是指我们看到的页面,视图模型是mvvm框架的核心,他是连接view和model的桥梁,它有两个方向,第一将后端传来的数据转换成页面可以看到的视图,第二,将用户在页面上的交互转化成为后端数据,我们称之为双向绑定。
总结mvvm模式的视图和模型是不能直接通信的,它们通过ViewModel来通信,ViewModel通常要实现一个observer观察者,当数据发生变化,ViewModel能够监听到数据的这种变化,然后通知到对应的视图做自动更新,而当用户操作视图,ViewModel也能监听到视图的变化,然后通知数据做改动,这实际上就实现了数据的双向绑定。并且MVVM中的View 和 ViewModel可以互相通信
vue框架可以理解为是ViewModel,它可以实现dom监听和数据绑定
vue的数据绑定原理

20200229115524399.png

当你把JavaScript对象传入vue实例作为data选项,vue会遍历此对象的所以属性,并使用Object.defineProperty把这些属性转换为getter和setter,每一个组件都有一个watcher实例,它会在组件渲染过程中,把接触过的数据记录为依赖,当依赖的setter被触发是,他会通知watcher,重而使关联的数据重新渲染,以下是代码展示。

<div id = "box"></div>
var obox = document.getElementById('box')
var obj = {}
object.defineProperty(obj,'myname',{
    get () {
        // obj设置了一个myname属性,当访问obj.myname属性会执行get方法
    },
    set (data) {
        // 当修改myname属性会执行set方法
        // data会得到你修改的值
        obox.innerHTML = data
    }
})
object.definePeoperty有一下缺点: {
1:无法监听es6的set,map变化
2:无法监听class类型的数据
3:属性的新增和删除也无法监听
4:数组元素的新整和删除也无法监听
}



日历

链接

个人资料

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

存档