前端的學習,不能僅僅依靠知識點的學習,實戰項目的操做能夠幫助咱們整理知識點以及提升編程能力,更有助於學習和實踐,最重要的是提升本身的項目經驗,對於找工做而言有着大大的幫助。javascript
做者用心之做,請動動你可愛的小手點亮大拇指
。你的鼓勵是做者繼續創做的動力...css
閱讀本篇文章以前,能夠先看看上一篇分享的內容,主要講大數據可視化的由來,與前端的淵源,主題風格設計,選擇比較流行的可視化第三方庫。html
」
一個基於Vue前端框架和第三方圖表庫Echarts構建的可視化大數據平臺,經過vue項目構建、指令的靈活運用、組件封裝、組件之間通訊,使內部圖表組件庫可實現自由替換和組合。以及一些功能模塊的設計及代碼實現。前端
老規矩先上效果圖(可視化酷屏展現公司品牌),後面會講這個實例。vue
線上體驗:jackchen0120.github.io/vueDataV/#/…java
下面接着繼續分享上一篇未講完的內容。webpack
先看效果圖:ios
自定義模態框已註冊全局小組件在/components/modal目錄文件,代碼以下(含註解):git
<template>
<transition name="fade"> <div class="modal-backdrop" v-if="visible"> <div class="modal"> <div class="modal-header"> {{ title }} <i class="iconfont icon-close close" @click="close"></i> </div> <div class="modal-body"> {{ content }} </div> <div class="modal-footer"> <button type="button" class="btn-close" @click="close" v-if="showCancle"> {{cancleText ? cancleText : '取消'}} </button> <button type="button" class="btn-confirm" @click="confirm"> {{confirmText ? confirmText : '肯定'}} </button> </div> </div> </div> </transition> </template> <script> export default { name: 'Modal', props: { // modal標題 title: { type: String, default: '提示' }, // modal內容 content: { type: String, default: '' }, // 是否顯示 visible: { type: Boolean, default: false }, // 是否顯示取消按鈕 showCancle: { type: Boolean, default: true }, // 確認按鈕文字 confirmText: { type: String, default: '確認' }, // 取消按鈕文字 cancleText: { type: String, default: '取消' } }, watch: { visible (curVal) { // 監聽visible值的變化 console.log(curVal) } }, methods: { // 關閉按鈕事件 close() { this.$emit('update:visible', false); }, // 肯定按鈕事件 confirm() { this.close(); this.$emit('confirm'); } } } </script> 複製代碼
在components/index.js目錄文件中註冊全局組件,以下圖:github
完整代碼以下:
// 引入自定義全局模態框組件
import modal from './modal' const components = { modal, }; // install 是默認的方法。當外界在 Vue.use() 這個組件的時候,就會調用自己的 install 方法,同時傳一個 Vue 這個類的參數。 const install = (Vue = {}) => { if (install.installed) return; Object.keys(components).forEach(component => { Vue.component(components[component].name, components[component]); }); install.installed = true; }; install.installed = false; if (typeof window !== "undefined" && window.Vue) { install(window.Vue); install.installed = true; } // 定義組件庫和install對象 const Vcomp = { ...components, install }; // 導出 export default Vcomp 複製代碼
在main.js中全局引用,以下圖:
可在任意頁面調用,代碼以下:
<template>
<div class="page"> <modal title="提示" :content="modalContent" :visible.sync="visible" @confirm="confirm"> </modal> </div> </template> export default { data() { return { visible: true, // 顯示模態框 modalContent: '這是一段自定義模態框消息' } }, methods: { confirm() { this.visible = false; console.log('點擊肯定') } } } 複製代碼
參數名 | 類型 | 說明 |
---|---|---|
visible | Boolean | 是否顯示,默認false |
title | String | 標題 |
content | String | 內容 |
confirmText | String | 確認按鈕文字,默認「確認」 |
cancleText | String | 取消按鈕文字,默認「取消」 |
showCancle | Boolean | 是否顯示,默認true |
update:visible | Boolean | 更新visible, 使用:visible.sync實現動態綁定 |
推薦一款簡單好用的數字滾動組件,vue-count-to
是一個無依賴,輕量級的vue組件,能夠自行覆蓋easingFn。你能夠設置 startVal 和 endVal,它會自動判斷計數或倒計時。支持vue-ssr,vue-countTo參考於countUp.js。
npm install -D vue-count-to
複製代碼
<template>
<countTo :startVal='startVal' :endVal='endVal' :duration='3000'></countTo> </template> <script> import countTo from 'vue-count-to'; export default { components: { countTo }, data () { return { startVal: 0, endVal: 2020 } } } </script> 複製代碼
屬性 | 描述 | 數據類型 | 默認值 |
---|---|---|---|
startVal | 開始值 | Number | 0 |
endVal | 結束值 | Number | 2020 |
duration | 持續時間,以毫秒爲單位 | Number | 3000 |
autoplay | 自動播放 | Boolean | true |
decimals | 要顯示的小數位數 | Number | 0 |
decimal | 十進制分割 | String | .(點) |
separator | 分隔符 | String | ,(逗號) |
prefix | 前綴 | String | ''(空字符串) |
suffix | 後綴 | String | ''(空字符串) |
useEasing | 使用緩和功能 | Boolean | true |
easingFn | 緩和回調 | Function | — |
*注意:當autoplay:true時,它將在startVal或endVal更改時自動啓動
函數名 | 描述 |
---|---|
mountedCallback | 掛載之後返回回調 |
start | 開始計數 |
pause | 暫停計數 |
reset | 重置countTo |
首頁動態列表組件顯示的數據,就引用了數字滾動特效,以下圖:
代碼以下圖:
如需查看完整源代碼請移步到做者的github倉庫
以前首頁大屏佈局採用的是絕對定位,加上總體屏幕縮放進行適配(簡單粗暴,不是很優雅
)。 如今推薦一種智能大屏適配方式,選用flexible.js是淘寶移動端自適應解決方案,源碼含註解以下:
// 首先是一個當即執行函數,執行時傳入的參數是window和document
(function flexible(window, document) { // 返回文檔的root元素 var docEl = document.documentElement; // 獲取設備的dpr,即當前設置下物理像素與虛擬像素的比值 var dpr = window.devicePixelRatio || 1; // 設置默認字體大小,默認的字體大小繼承自body function setBodyFontSize() { if (document.body) { // 調整body標籤的fontSize,fontSize = (12 * dpr) + 'px' document.body.style.fontSize = 12 * dpr + 'px'; } else { document.addEventListener('DOMContentLoaded', setBodyFontSize); } } setBodyFontSize(); // set 1rem = viewWidth / 24 function setRemUnit() { // 設置root元素的fontSize = 其clientWidth / 24 + 'px' var rem = docEl.clientWidth / 24; docEl.style.fontSize = rem + 'px'; } setRemUnit(); // 當頁面展現或從新設置大小的時候,觸發從新 window.addEventListener('resize', setRemUnit); window.addEventListener('pageshow', function(e) { if (e.persisted) { setRemUnit(); } }); // 檢測0.5px的支持,支持則root元素的class中有hairlines if (dpr >= 2) { var fakeBody = document.createElement('body'); var testElement = document.createElement('div'); testElement.style.border = '.5px solid transparent'; fakeBody.appendChild(testElement); docEl.appendChild(fakeBody); if (testElement.offsetHeight === 1) { docEl.classList.add('hairlines'); } docEl.removeChild(fakeBody); } })(window, document); 複製代碼
設計稿尺寸是1920px*1080px,因此將屏幕分紅24等份。
// 先下載插件到本地
git clone https://github.com/flashlizi/cssrem 複製代碼
進入packages目錄:Sublime Text -> Preferences -> Browse Packages... 以下圖:
將下載到本地的cssrem目錄複製到packges目錄裏,以下圖:
而後重啓Sublime Text,參數配置以下圖:
若是小夥伴使用的vscode編輯器,也能夠安裝此插件,打開擴展,搜索cssrem,點擊安裝,以下圖:
配置設置,以下圖:
改完後重啓,插件效果如圖:
Flex是Flexible Box的縮寫,意爲」彈性佈局」,用來爲盒狀模型提供最大的靈活性。能夠簡便、完整、響應式地實現各類頁面佈局。這裏推薦阮一峯老師的Flex佈局教程。
動手以前,先來分析一下整個頁面設計佈局,總體佈局分爲上(頭部模塊)和下(主體模塊),主體模塊又分爲左中右三部分。主體中間又分爲上(數字滾動模塊)和下(地圖模塊)。
頭部佈局樣式採用的是定位position,主體模塊column列容器,分三列,佔比 3 : 5 : 3。主體代碼以下:
<section class="mainbox">
<div class="item left"> flex: 3; </div> <div class="item center"> flex: 5; </div> <div class="item right"> flex: 3; </div> </section> 複製代碼
.mainbox {
min-width: 1024px; max-width: 1920px; padding: 0.125rem 0.125rem 0; display: flex; .item { flex: 3; &.center { flex: 5; margin: 0 0.125rem 0.1rem; overflow: hidden; } } } 複製代碼
全屏設置背景圖及頭部佈局樣式,能夠直接在/src/views/Brand.vue目錄文件查看源代碼。
補充說明頭部有展現天氣和當前時間,天氣數據實時展現,經過axios的get方法調用第三方免費天氣API接口,而且設置每小時獲取一次最新數據。代碼實現以下:
mounted() {
this.getWeather(); this.timer = setInterval(() => { this.getWeather(); }, 1000 * 60 * 60) }, methods: { getWeather() { // 第三方天氣api接口 axios.get('https://www.tianqiapi.com/api/', { params: { appid: '26148275', appsecret: '2id6H48Y', version: 'v6' } }).then(res => { if (res.data) { if (res.data.wea_img == 'xue') { this.imgSrc = require('../assets/img/brand/xue.png'); } else if (res.data.wea_img == 'yin') { this.imgSrc = require('../assets/img/brand/yin.png'); } else if (res.data.wea_img == 'yu' || res.data.wea_img == 'bingbao') { this.imgSrc = require('../assets/img/brand/yu.png'); } else if (res.data.wea_img == 'yun') { this.imgSrc = require('../assets/img/brand/yun.png'); } else if (res.data.wea_img == 'wu') { this.imgSrc = require('../assets/img/brand/wu.png'); } else if (res.data.wea_img == 'shachen') { this.imgSrc = require('../assets/img/brand/shachen.png'); } else if (res.data.wea_img == 'lei') { this.imgSrc = require('../assets/img/brand/lei.png'); } else { this.imgSrc = require('../assets/img/brand/qing.png'); } this.weatcherData = res.data; } }).catch(err => { console.log(err) }) } } 複製代碼
當前時間代碼實現以下:
mounted() {
this.nowTimes(); }, methods: { timeFormate(timeStamp) { //顯示當前時間 let newDate = new Date(timeStamp); let year = newDate.getFullYear(); let month = newDate.getMonth() + 1 < 10 ? '0' + (newDate.getMonth() + 1) : newDate.getMonth() + 1; let date = newDate.getDate() < 10 ? '0' + newDate.getDate() : newDate.getDate(); let hh = newDate.getHours() < 10 ? '0' + newDate.getHours() : newDate.getHours(); let mm = newDate.getMinutes() < 10 ? '0' + newDate.getMinutes() : newDate.getMinutes(); let ss = newDate.getSeconds() < 10 ? '0' + newDate.getSeconds() : newDate.getSeconds(); let week = newDate.getDay(); let weeks = ['日', '一', '二', '三', '四', '五', '六']; let getWeek = '星期' + weeks[week]; this.week = getWeek; this.date = year + '.' + month + '.' + date; this.nowTime = hh + ':' + mm + ':' + ss; }, nowTimes() { this.timeFormate(new Date()); setInterval(this.nowTimes, 1000); this.clear(); }, clear() { clearInterval(this.nowTimes) this.nowTimes = null; }, } 複製代碼
index.html引入cdn
vue.config.js配置webpack
<div class="chart" id="chart" style="width: 480px; height: 240px;"></div>
複製代碼
let myChart = echarts.init(document.getElementById('chart'));
複製代碼
let option = {
xAxis: { type: 'category', boundaryGap: false, data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'] }, yAxis: { type: 'value' }, series: [{ data: [820, 932, 901, 934, 1290, 1330, 1320], type: 'line', areaStyle: {}, smooth: true }] }; 複製代碼
myChart.setOption(option);
// 讓圖表跟隨屏幕自適應 window.addEventListener("resize", () => { myChart.resize(); }); 複製代碼
如需瞭解更多,請移步到Echarts官網查看相關文檔。
通常直接去echarts官網查找相似實例,適當分析,而且引入到頁面中,再根據需求定製圖表。官方實例地址:echarts.apache.org/examples/zh…
好比上圖的效果是如何實現的呢?
做者悄悄地告訴你,其實有個很簡單的方法,直接在Echarts社區查找,由於社區有不少活躍的Echarts使用者,常常貢獻一些很是棒的圖表示例。
本項目參考實例地址:gallery.echartsjs.com/editor.html…,通過修改調整,最終呈現的效果如上圖。已封裝註冊全局小組件,源代碼在/src/components/companySummary/business.vue目錄文件,請自行查看。
也是參考社區例子:模擬飛機航線動效
實現步驟:
這個例子是擴展案例,你們之後能夠多看看社區裏面的實例。
/* 約束屏幕尺寸 */
@media screen and (max-width: 1024px) { html { font-size: 42px !important; } } @media screen and (min-width: 1920) { html { font-size: 80px !important; } } 複製代碼
先上效果圖
上圖效果,做者已封裝註冊全局小組件,源代碼在/src/components/companySummary/wordCloud.vue目錄文件,請自行查看。
首先下載echarts-wordcloud.min.js壓縮文件(存放路徑:/src/assets/js),並導入到wordCloud.vue模板文件中。代碼以下:
<template>
<div class="word-container"> <div class="chart" id="chart_right1"></div> </div> </template> <script> import '@/assets/js/echarts-wordcloud.min' export default { name: "wordCloud", data() { return { timer: null } }, mounted() { this.getEchartRight1(); this.timer = setInterval(() => { this.getEchartRight1(); }, 5000) }, methods: { getEchartRight1() { let myChart = echarts.init(document.getElementById('chart_right1')); let option = { // tooltip: { // show: false // }, series: [{ type: 'wordCloud', gridSize: 1, sizeRange: [12, 50], rotationRange: [-90, 90], rotationStep: 45, shape: 'diamond', width: '90%', textPadding: 0, autoSize: { enable: true, minSize: 6 }, textStyle: { normal: { textBorderColor: 'rgba(255,255,255,0.3)', textBorderWidth: 1, color: () => { return 'rgb(' + [ Math.round(Math.random() * 160), Math.round(Math.random() * 160), Math.round(Math.random() * 160) ].join(',') + ')'; } }, emphasis: { fontSize: 20, // shadowBlur: 10, // shadowColor: 'rgba(255,255,255, .1)' } }, data: [{ name: '區塊鏈', value: 810 }, { name: '雲計算', value: 520 },{ name: "人工智能", value: 928 },{ name: "大數據", value: 906 },{ name: "工業互聯網", value: 825 },{ name: "醫療", value: 514 },{ name: "質量溯源", value: 486 },{ name: "政務", value: 53 },{ name: "密碼學", value: 927 },{ name: "金融行業", value: 1308 },{ name: "供應鏈", value: 693 },{ name: "公有鏈", value: 611 },{ name: "私有鏈", value: 512 },{ name: "聯盟鏈", value: 382 },{ name: "數據共享", value: 312 },{ name: "文創版權", value: 187 },{ name: "天河鏈", value: 163 },{ name: "數據存證", value: 104 },{ name: "UDFS存儲", value: 3 },{ name: "在線教育", value: 31 },{ name: "關聯分析", value: 941 },{ name: "智慧停車", value: 585 },{ name: "鏈雲生態", value: 473 },{ name: "應用層", value: 358 },{ name: "網絡層", value: 246 },{ name: "數據層", value: 207 },{ name: "基礎層", value: 194 },{ name: "智能合約", value: 104 },{ name: "去中心化", value: 87 },{ name: "數字貨幣", value: 415 },{ name: "酷屏", value: 253 },{ name: "可視化", value: 211 },{ name: "P2P", value: 116 },{ name: "數據挖掘", value: 1309 }] }] } myChart.setOption(option, true); window.addEventListener('resize', () => { myChart.resize(); }); }, }, beforeDestroy() { clearInterval(this.timer); } }; </script> 複製代碼
參考配置說明:github.com/ecomfe/echa…
若是感受還不錯的話,老鐵們是否是來github裏賞個★Star鼓勵一哈。後續會持續更新和優化,也期待你們的交流。
」
閱讀做者相關優質文章
獲取更多項目實戰經驗及各類源碼資源,請關注做者公衆號:懶人碼農