<table>
<tr>
<td>姓名:</td>
<td contentEditable="true"></td>
</tr>
<tr>
<td>密碼:</td>
<td contentEditable="true"></td>
</tr>
</table>
作者通過以進度條的設計深入淺出的講解關于FUI的設計思路。雖然FUI設計看起來很復雜,只要找準規律,從一些作品中總結分析細節,再運用到我們的設計中。想要了解的小伙伴可以嘗試一下。
前言
看到上期小伙伴想了解一下 FUI 的設計教程,所以這次再次和大家聊一下關于 FUI 的設計風格,我們以“進度條”的設計教程為例,深入淺出的聊一下關于 FUI 的設計思路,因為主要設計思路的延展,所以不會出現具體的數據參數,小伙伴們要諒解啊。
目錄
1.風格介紹
2.設計思路
3.總結
1.風格介紹
關于 FUI 的定義,閱讀過我上一篇文章的小伙伴可能對 FUI 的定義有了一個較為清晰的定義,即 FUI 是:虛構的、未來的、幻想的用戶界面。
接下來我會向大家簡單介紹一下 FUI 主要的兩大設計風格:軍事風格和機甲風格(也可以叫做機械風格)。
1.軍事風格
軍事風格的特點在于:“直接明了”。因為在殘酷的戰爭中時間就是生命,士兵必須保證“快速、準確、直接”才能保證戰斗的勝利,所以會盡量避免與操作業務無關的。你也可以理解為當下最前沿的的設計理念“less is more。”例如下圖,在界面設計中幾乎都是利用簡單的幾何設計語言完成。
2.機甲風格
機甲風格相對于軍事風格的最大特點就是:“具有一定的裝飾圖形元素,或多或少。”機甲風格最大的特點便是具有機械或者機甲風格的裝飾元素,其中多為異形元素。其靈感來源于工業設計,從機械和機甲的工業設計語言中提取圖形元素,在運用到界面設計上。如下圖,異形的機甲風格讓機器人的頭部設計顯得更加統一,如果換成當前流行的扁平化設計,可能就顯得有點奇怪了。
機甲風格的發展歸功于科幻題材故事的發展,為人們打開腦洞,暢想更多的可能性。在設計上激發了 FUI 的誕生,無論是賽博朋克、廢土題材、還是漫威、DC宇宙中的科幻影視作品中我們都能看到機甲風格的界面設計。
2.設計思路
設計樣式 – 軍事風格
我們從以上的設計風格中抓去我們需要的關鍵詞進行示例設計,首先我們看軍事風格的關鍵詞是“直接明了、快速、準確、直接,”我們轉換成我們平時的設計語言就是:“極簡風格,”這樣是不是更好理解了。例如圖例中,頁面整體十分統計,利用簡潔幾何語言進行設計。
接下來我們做一個簡單的軍事風格的進度條:第一步,找參考!!!這一步很重要,很多同學都很容易就忽視這一點,一心一意的閉門造車,絕不借鑒學習其它優秀作品。這里向大家推薦 HUDS + GUIS 設計公司,這里有我們許多我們耳熟能詳的影視作品中的 FUI 設計。
第二步,臨摹,臨摹可以說是學習他人技巧的最快方式,從中我們可以學習到許多設計中的細節,日后我們可以運用到自己的設計當中。我借鑒臨摹了下面的進度條樣式。
我們可以放入界面當中感受一下視覺效果:
設計樣式 – 機甲風格
我們再來進階一下,設計一個機甲元素的的進度條。
機甲風格看似裝飾圖形復雜,設計難度復雜,但其實我們只需要掌握好 – “提煉元素”這項技能就能完美應對機甲風格的設計。
我們再回顧對創意設計的定義:是把再簡單不過的東西或想法不斷延伸給予的另一種表現方式。這里我們可以理解為將機甲元素進行提煉總結,延伸到彈框設計當中。例如下圖,漂亮的小姐姐一秒鐘變機械美女,就是通過對機械元素延展到模特身上。
第一步,照一張你喜歡的不錯的參考,這里你可以找成熟的界面設計作品,也可以找一張不錯的關于機甲風格的參考,以便于自己進行元素提取。這里我們以大家熟悉的高達為例:
我們從中提取我們需要的圖形,如下圖:
最后我們我們需要仔細思考將圖形進行組合,多嘗試幾次他們的組合方式。這里我對提取的元素進行了二次加工,將圖形一和圖形四進行了結合,打破固有的組合規律,讓圖形看起來更加生動。
最后我們可以放入界面當中感受一下視覺效果:
3.總結
FUI 的設計看起來復雜,難以下手,但其實也是有規律可循,我們可以從作品中理性的去分析其中的設計細節,提煉總結,最終再落實到實際的設計作品當中。當然最好你能先了解一下它的設計理念以及發展,就像 FUI 是“虛構的、未來的、幻想的界面設計”一樣。
---來自姜正
轉載自簡書
作者:極創設計
鏈接:https://www.jianshu.com/p/77665c771153
來源:簡書
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。
藍藍設計( m.paul-jarrel.com )是一家專注而深入的界面設計公司,為期望卓越的國內外企業提供卓越的UI界面設計、BS界面設計 、 cs界面設計 、 ipad界面設計 、 包裝設計 、 圖標定制 、 用戶體驗 、交互設計、 網站建設 、平面設計服務
<view class="gallery">
<view class="item" wx:for="{{images}}" wx:key="">
<image src="{{item}}" data-src="{{item}}" bindtap="previewImage" mode="aspectFill" />
<!-- 刪除按鈕 -->
<view class="delete" bindtap="delete" data-index="{{index}}">X</view>
</view>
<view class="item" bindtap="chooseImage">
<view class='addIcon'>+</view>
</view>
</view>
<button type="primary" bindtap="submit">提交</button>
————————————————
/* pages/index/index.wxss */
/*畫廊*/
.gallery {
width:630rpx;
margin: 0 auto;
display: flex;
justify-content: flex-start;
flex-wrap: wrap;
}
/*每張圖片所占容器*/
.item {
position: relative;
margin:10rpx 5rpx;
width: 200rpx;
height: 200rpx;
}
.item image{
width: 100%;
height: 100%;
}
/*add按鈕*/
.item .addIcon{
position:relative;
width:200rpx;
height:200rpx;
text-align:center;
line-height:200rpx;
font-size:80rpx;
background: #f2f2f2;
color: #555;
}
/*刪除按鈕*/
.delete {
position:absolute;
right:0;
top:0;
/* background:#ccc; */
opacity:1;
height: 36rpx;
font-size:22rpx;
font-weight:700;
padding:0 8rpx 0 10rpx;
}
————————————————
var that;
Page({
data: {
images: [],
uploadedImages: [],
//imageWidth: getApp().screenWidth / 4 - 10
},
onLoad: function (options) {
that = this; var objectId = options.objectId; console.log(objectId);
},
chooseImage: function () {
// 選擇圖片
wx.chooseImage({
count: 3, // 默認9
sizeType: ['compressed'],
sourceType: ['album', 'camera'],
// 可以指定來源是相冊還是相機,默認二者都有
success: function (res) {
// 返回選定照片的本地文件路徑列表,tempFilePath可以作為img標簽的src屬性顯示圖片
var tempFilePaths = res.tempFilePaths;
console.log(tempFilePaths);
that.setData({
images: that.data.images.concat(tempFilePaths)
});
}
})
},
// 圖片預覽
previewImage: function (e) {
//console.log(this.data.images);
var current = e.target.dataset.src
wx.previewImage({
current: current,
urls: this.data.images
})
},
// submit: function () {
// // 提交圖片,事先遍歷圖集數組
// that.data.images.forEach(function (tempFilePath) {
// new AV.File('file-name', {
// blob: {
// uri: tempFilePath,
// },
// }).save().then(
// // file => console.log(file.url())
// function (file) {
// // 先讀取
// var uploadedImages = that.data.uploadedImages;
// uploadedImages.push(file.url());
// // 再寫入
// that.setData({
// uploadedImages: uploadedImages
// }); console.log(uploadedImages);
// }
// ).catch(console.error);
// });
// wx.showToast({
// title: '評價成功', success: function () {
// wx.navigateBack();
// }
// });
// },
delete: function (e) {
var index = e.currentTarget.dataset.index; var images = that.data.images;
images.splice(index, 1);
that.setData({
images: images
});
}
})
————————————————
<button data-name="shareBtn" open-type="share" plain="true">轉發</button>
添加plain=”true”后button的邊框樣式可自定義 ↓ ↓
button[plain]{ border:0 }
//轉發
onShareAppMessage: function (options) {
var that = this;
// 設置菜單中的轉發按鈕觸發轉發事件時的轉發內容
var shareObj = {
title: "這是一個標題!", // 默認是小程序的名稱(可以寫slogan等)
//path: '/page/index/index/user?id=123', // 默認是當前頁面,必須是以‘/’開頭的完整路徑
imageUrl: '../../img/xiaochengxu-share.jpg', //自定義圖片路徑,可以是本地文件路徑、代碼包文件路徑或者網絡圖片路徑,支持PNG及JPG,不傳入 imageUrl 則使用默認截圖。顯示圖片長寬比是 5:4
success: function (res) {
// 轉發成功之后的回調
if (res.errMsg == 'shareAppMessage:ok') {
}
},
fail: function (res) {
// 轉發失敗之后的回調
if (res.errMsg == 'shareAppMessage:fail cancel') {
// 用戶取消轉發
console.log("用戶取消轉發");
} else if (res.errMsg == 'shareAppMessage:fail') {
// 轉發失敗,其中 detail message 為詳細失敗信息
}
},
complete: function(){
// 轉發結束之后的回調(轉發成不成功都會執行)
},
};
// 來自頁面內的按鈕的轉發
if(options.from == 'button') {
var eData = options.target.dataset;
console.log(eData.name); // shareBtn
// 此處可以修改 shareObj 中的內容
//shareObj.path = '/pages/btnname/btnname?btn_name=' + eData.name;
}
// 返回shareObj
return shareObj;
————————————————
<swiper indicator-dots="{{indicatorDots}}" autoplay="{{autoplay}}" interval="{{interval}}" duration="{{duration}}" circular="{{duration}}" current="{{swiperCurrent}}" bindchange="swiperChange" class="swiper">
<block wx:for="{{imgUrls}}" wx:key="unique">
<swiper-item>
<image src="{{item}}" class="img" bindtap="swipclick" />
</swiper-item>
</block>
</swiper>
————————————————
/* swiper {
height: 421.5rpx;
} */
swiper-item image {
width: 100%;
height: 100%;
}
.swiper-container{
width: 100%;
position: relative;
}
.swiper-container .swiper{
height: 300rpx;
}
.swiper-container .swiper .img{
width: 100%;
height: 100%;
}
————————————————
const app = getApp()
Page({
data: {
swiperCurrent: 0,
indicatorDots: true,
autoplay: true,
interval: 3000,//自動切換時間間隔
duration: 800,//滑動動畫時長
circular: true,//是否采用銜接滑動
imgUrls: [
'../../img/index/1.jpeg',
'../../img/index/2.jpeg',
'../../img/index/3.jpeg'
]
},
//輪播圖的切換事件
swiperChange: function (e) {
this.setData({
swiperCurrent: e.detail.current
})
//console.log(e.detail.current);
},
//點擊指示點切換
chuangEvent: function (e) {
this.setData({
swiperCurrent: e.currentTarget.id
})
},
//點擊圖片觸發事件
swipclick: function (e) {
console.log(this.data.swiperCurrent);
wx.switchTab({
url: this.data.links[this.data.swiperCurrent]
})
},
})
————————————————
前提:真機和PC端在同一個局域網內。
1、安裝nodejs環境 (node -v 查看版本號)
2、在所在的項目下輸入命令:npm install anywhere -g
3、直接輸入命令:anywhere,這里瀏覽器自動打開所有項目的根目錄,點擊就可以看到,同一網段下,然后手機直接預覽這個地址就可以
————————————————
<view class="gallery">
<view class='tipTitle'>
快去上傳自己的照片吧
</view>
<view class='item-ot'>
<view class="item">
<!-- 添加按鈕 -->
<view class="addIcon" bindtap="chooseImage" wx:if="{{imgBoolean}}">
<view class=''>+</view>
</view>
<!-- 上傳的圖 -->
<view class='itemImg' >
<image src="{{item}}" data-src="{{item}}" bindtap="previewImage" mode="aspectFill" />
<!-- 刪除按鈕 -->
<view class="delete" bindtap="deleteImg" data-index="{{index}}">X</view>
</view>
<view class='boxStyle'></view>
</view>
<view class='itemTxt'>正面照</view>
</view>
<view class='uploadFinish'>
<a class="uploadFinishBtn" href="javasctipt:;" bindtap="submit">提 交</a>
</view>
</view>
/*畫廊*/
.gallery {
width:100%;
margin: 0 auto;
display: flex;
justify-content: flex-start;
flex-wrap: wrap;
background: #fffaf0;
}
/*每張圖片所占容器*/
.item-ot{
margin:0 auto;
width: 100%;
height: 100%;
}
.item {
position:relative;
margin:0 auto;
width:370rpx;
height:490rpx;
background:#eee;
border:2rpx solid #f9c4c2;
/* overflow:hidden; */
}
.itemImg{
position: absolute;
left: 0;
top:0;
width: 100%;
height: 100%;
overflow: hidden;
z-index:1;
}
.itemImg image{
width: 100%;
height: 100%;
}
/*add按鈕*/
.addIcon{
position:absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
text-align:center;
line-height:490rpx;
font-size:80rpx;
background: #fff;
color: #999;
z-index:2;
}
/*刪除按鈕*/
.delete {
position:absolute;
right:0;
top:0;
/* background:#ccc; */
opacity:1;
height: 36rpx;
font-size:22rpx;
font-weight:700;
padding:0 8rpx 0 10rpx;
color: #999;
}
.itemTxt{
text-align: center;
font-size: 30rpx;
color: #999;
margin-top: 50rpx;
margin-bottom: 70rpx;
font-weight: 700;
}
.uploadFinish{
width: 100%;
height: 100%;
padding: 0 30rpx;
box-sizing: border-box;
}
.uploadFinishBtn{
background: #ff6666;
color: #fff;
display: block;
width: 100%;
padding: 26rpx 0;
text-align: center;
font-size: 36rpx;
border-radius: 10rpx;
margin-bottom: 40rpx;
}
.tipTitle{
text-align: center;
font-size: 30rpx;
color: #f6a29d;
font-weight: 700;
width: 100%;
margin: 50rpx 0;
}
.boxStyle{
width:300rpx;
height:100rpx;
position:absolute;
bottom:-1rpx;
border-radius:50%;
box-shadow:0rpx 10rpx 100rpx #fddbd9;
margin-left:35rpx;
}
Page({
data: {
uploadedImages: [],
imgBoolean: true,
},
onLoad: function (options) {
var that = this;
},
chooseImage: function () {
var that = this;
// 選擇圖片
wx.chooseImage({
count: 1, // 默認9
sizeType: ['original', 'compressed'], // 可以指定是原圖還是壓縮圖,默認二者都有
sourceType: ['album', 'camera'], // 可以指定來源是相冊還是相機,默認二者都有
success: function (res) {
// 返回選定照片的本地文件路徑列表,tempFilePath可以作為img標簽的src屬性顯示圖片
var tempFilePaths = res.tempFilePaths
that.setData({
item: tempFilePaths[0],
imgBoolean: false
});
}
})
},
// 圖片預覽
previewImage: function (e) {
var current = e.target.dataset.src
wx.previewImage({
current: current,
urls: [current]
})
console.log("這是1" + current);
},
//刪除圖片
deleteImg: function (e) {
var that = this;
var images = that.data.uploadedImages;
that.setData({
uploadedImages: images,
imgBoolean: true
});
},
// submit: function () {
// },
})
],
如果想控制百分比最大到100% 可添加
yAxis : [
{
type : 'value',
max:100,//Y軸最大值 不寫的話自動調節
axisLabel:{formatter:'{value} %'}
}
],
> max:100,//Y軸最大值 不寫的話自動
<table>
<tr>
<td>姓名:</td>
<td contentEditable="true"></td>
</tr>
<tr>
<td>密碼:</td>
<td contentEditable="true"></td>
</tr>
</table>
語言設置
校驗消息默認是英文的,定義中文或其他語言的錯誤提示消息
-
import VeeValidate from 'vee-validate';
-
import Vue from 'vue'
-
Vue.use(VeeValidate)
-
-
var dict = {
-
zh_CN: {
-
messages: {
-
required: function(field){
-
return field + '不能為空!';
-
},
-
between: function(field){
-
return field + '輸入不符合設定規則!';
-
},
-
min : function (field,leng) {
-
return field + '長度不能小于'+leng+'位';
-
}
-
}
-
}
-
};
-
-
VeeValidate.Validator.localize('zh_CN', dict.zh_CN);
校驗的時候需要設置語言
this.$validator.localize('zh_CN');
錯誤消息顯示
顯示指定字段的第一個錯誤
this.$validator.first('fieldname')
顯示所有字段的第一個錯誤消息
this.$validator.errors.all()
配置
路由攔截配置不需要修改之前的代碼,匹配的url請求會直接通過mock而不是請求服務器
-
const handler = req => {
-
return {mock數據};
-
}
-
Mock.mock('url攔截規則,正則表達式',handler)
配置延遲時間
模擬服務器請求的異步特性
-
Mock.setup({
-
timeout:1000
-
})
模塊化
多人協作,或者中大型的項目需要把store分為模塊
-
const a = {
-
state : {foo:1},
-
mutations : {hello(state)=> {}},
-
modules : {
-
...嵌套
-
}
-
}
-
const b = {}
-
const store = {
-
state : {},
-
mutations : {},
-
actions : {},
-
modules : {
-
module_name_a:a,
-
module_name_b:b
-
}
-
}
在調用的時候,state 有命名空間的,而mutation和actions都與父模塊共用同樣的命名空間所以不能定義與父模塊同名的mutation 或 action
獲取模塊的state
this.$store.state.module_name_a.foo
調用模塊的mutation
this.$store.commit('hello')
namespace
定義了namespace ,mutations 和 action 會帶上模塊的命名: module_name/muation
-
const store = {
-
modules : {
-
namespace : true,
-
a: {
-
muations : {
-
test(state) => {...}
-
}
-
}
-
}
-
}
這時候調模塊內的mutation
this.$store.commit('a/test')
日期選擇控件
設置默認值
<datepicker v-model="mydate" </datepicker>
日期格式化
<datepicker :format="'yyyy-MM-dd'"> </datepicker>
語言選擇(默認是英文)
導入語言資源文件,然后再設置:language
設置成中文
-
藍藍設計的小編 http://m.paul-jarrel.com