文約2500字,建議閱讀9分鐘
本文分享幾個值得學習和使用的前端低代碼開源項目,更深入地了解什么是低代碼。
近幾年,在技術領域低代碼是比較熱門的話題,比如阿里云推出了釘釘低代碼,通過簡單的拖拽、配置,即可完成業務應用的搭建,騰訊云則是推出了微搭,通過行業化模板、拖放式組件和可視化配置快速構建多端應用。
低代碼是基于可視化和模型驅動理念,結合云原生與多端體驗技術,它能夠在多數業務場景下實現大幅度的提效降本,為專業開發者提供了一種全新的高生產力開發范式。下面就來分享幾個值得學習和使用的前端低代碼開源項目,更深入地了解什么是低代碼。
1 Appsmith
Appsmith 是一款開源低代碼框架,主要用于構建管理面板、內部工具和儀表板等,允許拖放 UI 組件來構建頁面,通過連接到任何 API、數據庫或 GraphQL 源,并使用 JavaScript 語言編寫邏輯,可以在短時間內創建內部應用程序。
項目鏈接:https://github.com/appsmithorg/appsmith
最新star:24288
2 LowCodeEngine
LowCodeEngine 由阿里巴巴釘釘宜搭團隊開發的低代碼框架,基于阿里云的云基礎設施和釘釘的企業數字化操作系統。使用者只需要基于低代碼引擎便可以快速定制符合自己業務需求的低代碼平臺。同時LowCodeEngine還提供了很多的基礎組件,可以幫助開發者快速地構建業務頁面。
項目鏈接:https://github.com/alibaba/lowcode-demo
最新star:887
3 Amis
Amis 是百度開源的一款前端低代碼框架,通過 JSON 配置就能生成各種后臺頁面,包括數據獲取、表單提交及驗證等功能,同時,Amis內置 100+ 種 UI 組件,能夠滿足各種頁面組件展現的需求,極大減少開發成本,甚至可以不需要了解前端。amis 在百度內部得到了廣泛使用,在 4 年多的時間里創建了 3w 多頁面,從內容審核到機器管理,從數據分析到模型訓練,amis 滿足了各種各樣的頁面需求。我們可以下載源碼,然后使用如下的命令來體驗。
項目鏈接:https://github.com/baidu/amis
最新star:12860
4 tmagic-editor
tmagic-editor是一款由騰訊技術中心出品的一款開源低代碼框架,能夠實現零代碼/低代碼生成頁面 , 可以快速搭建可視化頁面生產平臺,讓非技術人員可以通過拖拽和配置,自助生成H5頁面、PC頁面、TV頁面,大大降低頁面生產成本 。
項目鏈接:https://github.com/Tencent/tmagic-editor
最新star:3112
5 dooring-electron-lowcode
dooring-electron-lowcode是一款功能強大,專業可靠的可視化頁面配置解決方案,致力于提供一套簡單方便、專業可靠、無限可能的H5落地頁最佳實踐。技術棧以react和typescript為主, 后臺采用nodejs開發, electron作為桌面端基礎方案。
項目鏈接:https://github.com/H5-Dooring/dooring-electron-lowcode
最新star:150
6 vite-vue3-lowcode
vite-vue3-lowcode 是一款基于Vite2.x + Vue3.x + TypeScript技術框架的的H5 低代碼平臺。目前只是一個簡單的模板,支持數據配置的導入和導出,配置的修改和刪除操作,用到的技術有sandbox 中執行自定義邏輯、monaco-editor 自定義代碼補全、vue3 createRenderer 自定義渲染器等。
項目鏈接:https://github.com/buqiyuan/vite-vue3-lowcode
最新star:2158
7 shida
shida是一個視頻可視化搭建項目,開發者可以通過拖拽就可以快速地生產一個短視頻,使用方式就像易企秀或百度 H5 等 h5 低代碼平臺一樣。shida的后端視頻合成部分是基于FFCreator進行開發的,FFCreator 是一個基于 node.js 的輕量、靈活的短視頻加工庫,只需要添加幾張圖片或視頻片段再加一段背景音樂,就可以快速生成一個很酷的視頻短片。
項目鏈接:https://github.com/tnfe/shida
最新star:363
8 quark-h5
quark-h5是一個使用Vue + Koa的前端低代碼框架,和大多數的前端低代碼框架一樣,采用的是編輯器生成頁面JSON數據,服務端負責存取JSON數據,渲染時從服務端取數據JSON交給前端模板處理。
項目鏈接:https://github.com/huangwei9527/quark-h5
最新star:3064
9 gods-pen
碼良是一個在線生成 H5 頁面并提供頁面管理和頁面編輯的平臺,用于快速制作 H5 頁面。用戶無需掌握復雜的編程技術,通過簡單拖拽、少量配置即可制作精美的頁面,可用于營銷場景下的頁面制作。同時,也為開發者提供了完備的編程接入能力,通過腳本和組件的形式獲得強大的組件行為和交互控制能力。
項目鏈接:https://github.com/ymm-tech/gods-pen
最新star:4247
10 luban-h5
魯班H5是基于Vue2.0開發的支持拖拽方式來快速生成頁面的低代碼平臺,功能基本類似于易企秀、Maka、百度等H5平臺。
項目鏈接:https://github.com/ly525/luban-h5
最新star:5654
11 mometa
mometa 并不是傳統主流的低代碼平臺(如 amis),mometa 是面向研發、代碼可視設計編輯平臺,更像是 dreamweaver、gui的可視編輯 工具。借助它,我們可以獲得所見即所得的可視編輯開發體驗。
項目鏈接:https://github.com/imcuttle/mometa
最新star:3469
12 h5-factory
h5-factory是專題頁面可視化編輯工具,可以通過拖拽來設計頁面,并且支持一鍵生成html文件。
項目鏈接:https://github.com/xuhaiqing/h5-factory
最新star:6
13 steedos-platform
steedos-platform是 Salesforce 低代碼平臺的開源替代方案,使用可視化工具進行模型設計, 頁面設計, 流程設計, 報表設計,只需點擊鼠標,就能快速創建應用程序,實現敏捷開發的新高度。在技術實現細節上,steedos-platform使用元數據定義對象,字段,配置,代碼,邏輯和頁面布局,并基于這些元數據自動生成系統的數據結構以及Steedos應用程序的用戶界面和自動化邏輯。
項目鏈接:https://github.com/steedos/steedos-platform/
最新star:951
14 lz-h5-edit
lz-h5-edit是一個H5低代碼編輯平臺,支持拖拽、縮放、旋轉、動畫、撤銷、重做、組合元素等方式來創建H5頁面。
項目鏈接:https://github.com/lzuntalented/lz-h5-edit
最新star:462
15 tefact
星搭開源無代碼編輯器,使用圖形化界面生成 網站、H5和表單,無需任何代碼即可生成應用程序。
項目鏈接:https://github.com/staringos/tefact/
最新star:244
16 fast-poster
fast-poster是一款使用Python+Vue開發的通用海報生成器,可以用來快速地生成海報。使用時只需要經過三步即可生成所需要的海報:啟動服務 > 編輯海報 > 生成代碼。
項目鏈接:https://github.com/psoho/fast-poster
最新star:408
17 openDataV
OpenDataV 是一款基于Vue3 + vite + TypeScript開發前端可視化低代碼平臺。支持拖拽式、可視化、低代碼數據可視化開發,你可以用它自由的拼接成各種炫酷的大屏,同時支持接入開發者自己開發的組件接入平臺。
項目鏈接:https://github.com/AnsGoo/openDataV
最新star:196
18 mall-cook
Mall-Cook 是一個基于 vue 開發的可視化商城搭建平臺,包括多頁面可視化構建、Json Schema 生成器(可視化搭建物料控制面板),實現組件流水線式標準接入平臺。最新版本使用 uni-app 重構物料、模板項目,支持生成 H5、小程序多端商城。
項目鏈接:https://github.com/wangyuan389/mall-cook
最新star:3632
19 form-generator
form-generator是一個基于Element UI表單設計及代碼生成器,可將生成的代碼直接運行在基于Element的vue項目中,也可導出JSON表單,使用配套的解析器將JSON解析成真實的表單。
項目鏈接:https://github.com/JakHuang/form-generator
最新star:7482
20 vjdesign
vjdesign是一款支持任何 vue 項目中的組件,不需要二次開發就可以定義支持的組件以及組件的屬性,并且對組件的屬性和數據的關系以及表單的交互行為也可以通過設計器配置實現。
項目鏈接:https://github.com/fyl080801/vjdesign
最新star:384
nillawebprojects里面是一些使用HTML5、CSS和JavaScript構建的小型項目。
推薦原因:vanillawebprojects這個項目很適合前端新手學習,每一個小項目都同時使用到了HTML+CSS+JS,這是前端最基礎的內容,扎實的掌握了前端三件套之后,對以后學習前端框架會有很大的幫助。里面一共包含了20個小項目,學會這幾個項目,相信你對HTML、CSS和JS會有一個更深刻的認知。
GitHub地址:https://github.com/bradtraversy/vanillawebprojects
JavaScript是最好的語言之一,尤其是在前端開發中。在本文中,您將找到7個為初學者提供免費源代碼的最佳javascript項目。
手把手教你7個有趣的JavaScript 項目-上「附源碼」(本篇)
手把手教你7個有趣的JavaScript 項目-下「附源碼」
如果您是javascript語言的初學者,則待辦事項列表應用程序是最好的和最容易的應用程序之一,如果您使用HTML CSS和一點點的javascript,則可以創建此簡單的待辦事項列表應用程序,您將找到源代碼這個js項目的底部。
<!DOCTYPE html>
<html lang="zh">
<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>
<style type="text/css">
$primary: #313e50;
$grey: #cdcdcd;
$secondary: #1dd2af;
%reset {
margin: 0;
padding: 0;
border: none;
outline: none;
background: transparent;
}
%transition {
transition: all 0.2s ease;
-webkit-transition: all 0.2s ease;
}
body {
background: #f1f1f1;
margin-top: 2rem;
}
/*PEN STYLES*/
.tasker {
max-width: 400px;
margin: 0 auto;
.error {
display: none;
background: rgba(237, 28, 36, 0.7);
color: #fff;
padding: 14px;
margin-bottom: 10px;
border-radius: 5px;
text-align: center;
}
ul {
@extend %reset;
background: #fff;
}
li,
.error,
button,
input {
@extend %reset;
font: 18px/1.25em Helvetica, Arial, Sans-serif;
}
}
.tasker-header {
display: inline-flex;
background: $primary;
justify-content: space-between;
width: 100%;
input,
button {
color: #fff;
box-sizing: border-box;
font-size: 1.25em;
padding: 14px;
}
input {
flex-grow: 2;
}
button {
@extend %transition;
background: $secondary;
border-left: 1px solid ($secondary * 1.05);
&:hover {
background: $secondary * 1.1;
}
}
}
.tasker-body {
.task {
display: block;
position: relative;
padding: 14px 40px 14px 14px;
border-bottom: 1px solid rgba(0, 0, 0, 0.1);
&:last-child {
border-bottom: none;
}
&:hover > button {
opacity: 1;
}
&.completed {
color: $grey;
text-decoration: line-through;
}
input {
margin-right: 10px;
}
button {
@extend %transition;
color: $grey;
margin: 14px;
position: absolute;
top: 0;
right: 0;
opacity: 0;
&:hover {
color: #ed1c24;
}
}
}
}
</style>
</head>
<body>
<!--PEN CODE-->
<div id="tasker" class="tasker">
<div id="error" class="error">Please enter a task</div>
<div id="tasker-header" class="tasker-header">
<input type="text" id="input-task" placeholder="Enter a task">
<button id="add-task-btn"><i class="fa fa-fw fa-plus"></i>
</button>
</div>
<div class="tasker-body">
<ul id="tasks"></ul>
</div>
</div>
<!--END PEN CODE-->
<script type="text/javascript">
(function() {
'use strict';
var tasker={
init: function() {
this.cacheDom();
this.bindEvents();
this.evalTasklist();
},
cacheDom: function() {
this.taskInput=document.getElementById("input-task");
this.addBtn=document.getElementById("add-task-btn");
this.tasklist=document.getElementById("tasks");
this.tasklistChildren=this.tasklist.children;
this.errorMessage=document.getElementById("error");
},
bindEvents: function() {
this.addBtn.onclick=this.addTask.bind(this);
this.taskInput.onkeypress=this.enterKey.bind(this);
},
evalTasklist: function() {
var i, chkBox, delBtn;
//BIND CLICK EVENTS TO ELEMENTS
for (i=0; i < this.tasklistChildren.length; i +=1) {
//ADD CLICK EVENT TO CHECKBOXES
chkBox=this.tasklistChildren[i].getElementsByTagName("input")[0];
chkBox.onclick=this.completeTask.bind(this, this.tasklistChildren[i], chkBox);
//ADD CLICK EVENT TO DELETE BUTTON
delBtn=this.tasklistChildren[i].getElementsByTagName("button")[0];
delBtn.onclick=this.delTask.bind(this, i);
}
},
render: function() {
var taskLi, taskChkbx, taskVal, taskBtn, taskTrsh;
//BUILD HTML
taskLi=document.createElement("li");
taskLi.setAttribute("class", "task");
//CHECKBOX
taskChkbx=document.createElement("input");
taskChkbx.setAttribute("type", "checkbox");
//USER TASK
taskVal=document.createTextNode(this.taskInput.value);
//DELETE BUTTON
taskBtn=document.createElement("button");
//TRASH ICON
taskTrsh=document.createElement("i");
taskTrsh.setAttribute("class", "fa fa-trash");
//INSTERT TRASH CAN INTO BUTTON
taskBtn.appendChild(taskTrsh);
//APPEND ELEMENTS TO TASKLI
taskLi.appendChild(taskChkbx);
taskLi.appendChild(taskVal);
taskLi.appendChild(taskBtn);
//ADD TASK TO TASK LIST
this.tasklist.appendChild(taskLi);
},
completeTask: function(i, chkBox) {
if (chkBox.checked) {
i.className="task completed";
} else {
this.incompleteTask(i);
}
},
incompleteTask: function(i) {
i.className="task";
},
enterKey: function(event) {
if (event.keyCode===13 || event.which===13) {
this.addTask();
}
},
addTask: function() {
var value=this.taskInput.value;
this.errorMessage.style.display="none";
if (value==="") {
this.error();
} else {
this.render();
this.taskInput.value="";
this.evalTasklist();
}
},
delTask: function(i) {
this.tasklist.children[i].remove();
this.evalTasklist();
},
error: function() {
this.errorMessage.style.display="block";
}
};
tasker.init();
}());
</script>
</body>
</html>
您可以使用javascript初學者創建的第二個小項目是時間軸,許多現代網站都使用該時間軸使網站更具交互性和動態性。
<!DOCTYPE html>
<html lang="zh">
<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>CSS創建垂直時間軸(里程碑)</title>
<style type="text/css">
*,
*::before,
*::after {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font: normal 16px/1.5 "Helvetica Neue", sans-serif;
background: #456990;
color: #fff;
overflow-x: hidden;
padding-bottom: 50px;
} /* INTRO SECTION
–––––––––––––––––––––––––––––––––––––––––––––––––– */
.intro {
background: #F45B69;
padding: 100px 0;
}
.container {
width: 90%;
max-width: 1200px;
margin: 0 auto;
text-align: center;
}
h1 {
font-size: 2.5rem;
}
/* TIMELINE
–––––––––––––––––––––––––––––––––––––––––––––––––– */
.timeline ul {
background: #456990;
padding: 50px 0;
}
.timeline ul li {
list-style-type: none;
position: relative;
width: 6px;
margin: 0 auto;
padding-top: 50px;
background: #fff;
}
.timeline ul li::after {
content: '';
position: absolute;
left: 50%;
bottom: 0;
transform: translateX(-50%);
width: 30px;
height: 30px;
border-radius: 50%;
background: inherit;
}
.timeline ul li div {
position: relative;
bottom: 0;
width: 400px;
padding: 15px;
background: #F45B69;
}
.timeline ul li div::before {
content: '';
position: absolute;
bottom: 7px;
width: 0;
height: 0;
border-style: solid;
}
.timeline ul li:nth-child(odd) div {
left: 45px;
}
.timeline ul li:nth-child(odd) div::before {
left: -15px;
border-width: 8px 16px 8px 0;
border-color: transparent #F45B69 transparent transparent;
}
.timeline ul li:nth-child(even) div {
left: -439px;
}
.timeline ul li:nth-child(even) div::before {
right: -15px;
border-width: 8px 0 8px 16px;
border-color: transparent transparent transparent #F45B69;
}
time {
display: block;
font-size: 1.2rem;
font-weight: bold;
margin-bottom: 8px;
}
/* EFFECTS
–––––––––––––––––––––––––––––––––––––––––––––––––– */
.timeline ul li::after {
transition: background .5s ease-in-out;
}
.timeline ul li.in-view::after {
background: #F45B69;
}
.timeline ul li div {
visibility: hidden;
opacity: 0;
transition: all .5s ease-in-out;
}
.timeline ul li:nth-child(odd) div {
transform: translate3d(200px, 0, 0);
}
.timeline ul li:nth-child(even) div {
transform: translate3d(-200px, 0, 0);
}
.timeline ul li.in-view div {
transform: none;
visibility: visible;
opacity: 1;
}
/* GENERAL MEDIA QUERIES
–––––––––––––––––––––––––––––––––––––––––––––––––– */
@media screen and (max-width: 900px) {
.timeline ul li div {
width: 250px;
}
.timeline ul li:nth-child(even) div {
left: -289px;
/*250+45-6*/
}
}
@media screen and (max-width: 600px) {
.timeline ul li {
margin-left: 20px;
}
.timeline ul li div {
width: calc(100vw - 91px);
}
.timeline ul li:nth-child(even) div {
left: 45px;
}
.timeline ul li:nth-child(even) div::before {
left: -15px;
border-width: 8px 16px 8px 0;
border-color: transparent #F45B69 transparent transparent;
}
}
</style>
</head>
<body>
<section class="intro">
<div class="container">
<h1>Vertical Timeline ↓</h1>
</div>
</section>
<section class="timeline">
<ul>
<li>
<div>
<time>1934</time> demo1
</div>
</li>
<li>
<div>
<time>1937</time> demo1
</div>
</li>
<li>
<div>
<time>1940</time> demo1
</div>
</li>
<li>
<div>
<time>1943</time> demo1
</div>
</li>
<li>
<div>
<time>1946</time> demo1
</div>
</li>
<li>
<div>
<time>1956</time> demo1
</div>
</li>
<li>
<div>
<time>1957</time> demo1
</div>
</li>
<li>
<div>
<time>1967</time>demo1
</div>
</li>
<li>
<div>
<time>1977</time> demo1
</div>
</li>
<li>
<div>
<time>1985</time> demo1
</div>
</li>
<li>
<div>
<time>2000</time> demo1
</div>
</li>
<li>
<div>
<time>2005</time> demo1
</div>
</li>
</ul>
</section>
<script type="text/javascript">
(function() {
'use strict';
// define variables
var items=document.querySelectorAll(".timeline li");
// check if an element is in viewport
// http://stackoverflow.com/questions/123999/how-to-tell-if-a-dom-element-is-visible-in-the-current-viewport
function isElementInViewport(el) {
var rect=el.getBoundingClientRect();
return (
rect.top >=0 &&
rect.left >=0 &&
rect.bottom <=(window.innerHeight || document.documentElement.clientHeight) &&
rect.right <=(window.innerWidth || document.documentElement.clientWidth)
);
}
function callbackFunc() {
for (var i=0; i < items.length; i++) {
if (isElementInViewport(items[i])) {
items[i].classList.add("in-view");
}
}
}
// listen for events
window.addEventListener("load", callbackFunc);
window.addEventListener("resize", callbackFunc);
window.addEventListener("scroll", callbackFunc);
})();
</script>
</body>
</html>
如果您想構建簡單而有趣的東西來練習JavaScript知識,那么使用HTML CSS和JS創建TIC TAC TOE游戲對您來說是個不錯的選擇,該游戲雖然簡單但并不容易,因此您需要專注于該項目的邏輯方面,因為它是該項目最具挑戰性的部分。
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>FreeCodeCamp: Tictactoe</title>
<style type="text/css">
@import url(https://fonts.googleapis.com/css?family=Yesteryear);
$app-background-color : #508ABB;
$app-row-height : 100%;
$winAnimStartColor : cyan;
$winAnimEndColor : #508ABB;
// html, body, div, span, a, li, td, th {
// font-family: 'Lato', sans-serif;
// font-weight: 300;
//
// }
@-webkit-keyframes winAnim{
0% {
background-color: $winAnimStartColor;
}
100% {
background-color: $winAnimEndColor;
}
}
@-moz-keyframes winAnim{
0% {
background-color: $winAnimStartColor;
}
100% {
background-color: $winAnimEndColor;
}
}
@-o-keyframes winAnim {
0% {
background-color: $winAnimStartColor;
}
100% {
background-color: $winAnimEndColor;
}
}
@keyframes winAnim {
0% {
background-color: $winAnimStartColor;
}
100% {
background-color: $winAnimEndColor;
}
}
@keyframes winAnim {
0% {
background-color: $winAnimStartColor;
}
100% {
background-color: $winAnimEndColor;
}
}
*{
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
outline-style:none;/*IE*/
}
.center-box{
margin : auto;
position: absolute;
top : 0;
right : 0;
bottom : 0;
left : 0;
}
html,body{
//background-image: linear-gradient(to bottom,#dddbd1,#d2dbdc);
background-color: #d2dbdc;
height : 100%;
width : 100%;
}
.app{
@extend .center-box;
width : 80%;
height : 70%;
max-width: 550px;
background-color : $app-background-color;
box-shadow: 0 5px 30px -5px rgba(0,0,0, .85);
border-radius: 10px;
.app-container,
.app-row{
height: $app-row-height;
}
}
.play-box,.symbol-option{
font-family: 'Yesteryear', cursive;
}
.play-box{
border-bottom : 2px solid #fff;
border-right : 2px solid #fff;
height : $app-row-height / 3;
cursor: pointer;
position: relative;
&.last-right{
border-right : none;
}
&.last-bottom{
border-bottom : none;
}
&.win {
-webkit-animation: winAnim .2s ease-out infinite;
-moz-animation: winAnim .2s ease-out infinite;
-o-animation: winAnim .2s ease-out infinite;
animation: winAnim .2s ease-out infinite;
animation : winAnim .5s infinite;
}
.symbol{
@extend .center-box;
width: 50%;
height : 50px;
text-align: center;
line-height : 50px;
font-size: 35px;
color : white;
}
}
.modal-content{
.content{
padding : 15px;
text-align: center;
margin : 0;
&.body{
line-height: 2;
}
}
.symbol-options{
width: 200px;
margin-top: 10px;
.symbol-option{
&:first-child{
margin-right: 10px;
}
&:last-child{
margin-left: 10px;
}
}
}
.warning-hr{
margin: 0;
}
}
</style>
</head>
<body>
<div class="app">
<div class="container-fluid app-container">
<div class="row app-row">
<div class="col-xs-4 play-box" id="0">
<div class="symbol"></div>
</div>
<div class="col-xs-4 play-box" id="1">
<div class="symbol"></div>
</div>
<div class="col-xs-4 play-box last-right" id="2">
<div class="symbol"></div>
</div>
<div class="col-xs-4 play-box" id="3">
<div class="symbol"></div>
</div>
<div class="col-xs-4 play-box" id="4">
<div class="symbol"></div>
</div>
<div class="col-xs-4 play-box last-right" id="5">
<div class="symbol"></div>
</div>
<div class="col-xs-4 play-box last-bottom" id="6">
<div class="symbol"></div>
</div>
<div class="col-xs-4 play-box last-bottom" id="7">
<div class="symbol"></div>
</div>
<div class="col-xs-4 play-box last-right last-bottom" id="8">
<div class="symbol"></div>
</div>
</div>
</div>
</div>
<div class="modal fade app-modal" tabindex="-1" role="dialog" aria-labelledby="mySmallModalLabel">
<div class="modal-dialog modal-size">
<div class="modal-content">
<h3 class="content heading">Warning!!!</h3>
<hr class="warning-hr">
<div class="content body">
Please save your time and don't even think you're smart. <br><strong><em>I'M SMARTER THAN YOU! HA-HA-HA!!!</em></strong> <br>
Wana try me? Chose : <br>
<div class="center-block symbol-options">
<button class="symbol-option btn btn-default btn-md" data-dismiss="modal">X</button> OR <button class="symbol-option btn btn-default btn-md" data-dismiss="modal">O</button>
</div>
</div>
</div>
</div>
</div>
<script src="../js/bundled/tictactoe.bundled.js">
</script>
</body>
</html>
許多現代網站和博客都使用倒數計時器來顯示倒數,例如,我們通過使用倒數計時器來告訴在線商店的訪問者,商品價格將在價格上漲后增加銷售量。具體時間。
<!DOCTYPE html>
<html lang="zh">
<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>CSS創建垂直時間軸(里程碑)</title>
<style type="text/css">
/* Variabes */
$orange: #ffa600;
$grey:#f3f3f3;
$white: #fff;
$base-color:$orange ;
/* Mixin's */
@mixin transition {
-webkit-transition: all 0.5s ease-in-out;
-moz-transition: all 0.5s ease-in-out;
transition: all 0.5s ease-in-out;
}
@mixin corners ($radius) {
-moz-border-radius: $radius;
-webkit-border-radius: $radius;
border-radius: $radius;
-khtml-border-radius: $radius;
}
body {
background:$base-color;
font-family: "HelveticaNeue-Light", "Helvetica Neue Light", "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif;
height:100%;
}
.wrapper {
width: 800px;
margin: 30px auto;
color:$white;
text-align:center;
}
h1, h2, h3 {
font-family: 'Roboto', sans-serif;
font-weight: 100;
font-size: 2.6em;
text-transform: uppercase;
}
#seconds, #tens{
font-size:2em;
}
button{
@include corners (5px);
background:$base-color;
color:$white;
border: solid 1px $white;
text-decoration:none;
cursor:pointer;
font-size:1.2em;
padding:18px 10px;
width:180px;
margin: 10px;
outline: none;
&:hover{
@include transition;
background:$white;
border: solid 1px $white;
color:$base-color;
}
}
</style>
</head>
<body>
<div class="wrapper">
<h1>Stopwatch</h1>
<h2>Vanilla JavaScript Stopwatch</h2>
<p><span id="seconds">00</span>:<span id="tens">00</span></p>
<button id="button-start">Start</button>
<button id="button-stop">Stop</button>
<button id="button-reset">Reset</button>
</div>
<script type="text/javascript">
window.onload=function () {
var seconds=00;
var tens=00;
var appendTens=document.getElementById("tens")
var appendSeconds=document.getElementById("seconds")
var buttonStart=document.getElementById('button-start');
var buttonStop=document.getElementById('button-stop');
var buttonReset=document.getElementById('button-reset');
var Interval ;
buttonStart.onclick=function() {
clearInterval(Interval);
Interval=setInterval(startTimer, 10);
}
buttonStop.onclick=function() {
clearInterval(Interval);
}
buttonReset.onclick=function() {
clearInterval(Interval);
tens="00";
seconds="00";
appendTens.innerHTML=tens;
appendSeconds.innerHTML=seconds;
}
function startTimer () {
tens++;
if(tens < 9){
appendTens.innerHTML="0" + tens;
}
if (tens > 9){
appendTens.innerHTML=tens;
}
if (tens > 99) {
console.log("seconds");
seconds++;
appendSeconds.innerHTML="0" + seconds;
tens=0;
appendTens.innerHTML="0" + 0;
}
if (seconds > 9){
appendSeconds.innerHTML=seconds;
}
}<script src="../js/bundled/tictactoe.bundled.js">
</script>
}
</script>
</body>
</html>
我可以用JavaScript構建游戲嗎?答案是肯定的,使用javascript甚至可以創建復雜的游戲,但是在這種情況下,我們將專注于一個簡單的游戲,該游戲可讓您練習HTML CSS和javascript技能。
<!DOCTYPE html>
<html lang="zh">
<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>使用js調用設備攝像頭并實現拍照</title>
<style type="text/css">
body {
text-align: center;
}
</style>
</head>
<body>
<script type="text/javascript">
// Global Variables
var DIRECTION={
IDLE: 0,
UP: 1,
DOWN: 2,
LEFT: 3,
RIGHT: 4
};
var rounds=[5, 5, 3, 3, 2];
var colors=['#1abc9c', '#2ecc71', '#3498db', '#e74c3c', '#9b59b6'];
// The ball object (The cube that bounces back and forth)
var Ball={
new: function (incrementedSpeed) {
return {
width: 18,
height: 18,
x: (this.canvas.width / 2) - 9,
y: (this.canvas.height / 2) - 9,
moveX: DIRECTION.IDLE,
moveY: DIRECTION.IDLE,
speed: incrementedSpeed || 9
};
}
};
// The paddle object (The two lines that move up and down)
var Paddle={
new: function (side) {
return {
width: 18,
height: 70,
x: side==='left' ? 150 : this.canvas.width - 150,
y: (this.canvas.height / 2) - 35,
score: 0,
move: DIRECTION.IDLE,
speed: 10
};
}
};
var Game={
initialize: function () {
this.canvas=document.querySelector('canvas');
this.context=this.canvas.getContext('2d');
this.canvas.width=1400;
this.canvas.height=1000;
this.canvas.style.width=(this.canvas.width / 2) + 'px';
this.canvas.style.height=(this.canvas.height / 2) + 'px';
this.player=Paddle.new.call(this, 'left');
this.paddle=Paddle.new.call(this, 'right');
this.ball=Ball.new.call(this);
this.paddle.speed=8;
this.running=this.over=false;
this.turn=this.paddle;
this.timer=this.round=0;
this.color='#2c3e50';
Pong.menu();
Pong.listen();
},
endGameMenu: function (text) {
// Change the canvas font size and color
Pong.context.font='50px Courier New';
Pong.context.fillStyle=this.color;
// Draw the rectangle behind the 'Press any key to begin' text.
Pong.context.fillRect(
Pong.canvas.width / 2 - 350,
Pong.canvas.height / 2 - 48,
700,
100
);
// Change the canvas color;
Pong.context.fillStyle='#ffffff';
// Draw the end game menu text ('Game Over' and 'Winner')
Pong.context.fillText(text,
Pong.canvas.width / 2,
Pong.canvas.height / 2 + 15
);
setTimeout(function () {
Pong=Object.assign({}, Game);
Pong.initialize();
}, 3000);
},
menu: function () {
// Draw all the Pong objects in their current state
Pong.draw();
// Change the canvas font size and color
this.context.font='50px Courier New';
this.context.fillStyle=this.color;
// Draw the rectangle behind the 'Press any key to begin' text.
this.context.fillRect(
this.canvas.width / 2 - 350,
this.canvas.height / 2 - 48,
700,
100
);
// Change the canvas color;
this.context.fillStyle='#ffffff';
// Draw the 'press any key to begin' text
this.context.fillText('Press any key to begin',
this.canvas.width / 2,
this.canvas.height / 2 + 15
);
},
// Update all objects (move the player, paddle, ball, increment the score, etc.)
update: function () {
if (!this.over) {
// If the ball collides with the bound limits - correct the x and y coords.
if (this.ball.x <=0) Pong._resetTurn.call(this, this.paddle, this.player);
if (this.ball.x >=this.canvas.width - this.ball.width) Pong._resetTurn.call(this, this.player, this.paddle);
if (this.ball.y <=0) this.ball.moveY=DIRECTION.DOWN;
if (this.ball.y >=this.canvas.height - this.ball.height) this.ball.moveY=DIRECTION.UP;
// Move player if they player.move value was updated by a keyboard event
if (this.player.move===DIRECTION.UP) this.player.y -=this.player.speed;
else if (this.player.move===DIRECTION.DOWN) this.player.y +=this.player.speed;
// On new serve (start of each turn) move the ball to the correct side
// and randomize the direction to add some challenge.
if (Pong._turnDelayIsOver.call(this) && this.turn) {
this.ball.moveX=this.turn===this.player ? DIRECTION.LEFT : DIRECTION.RIGHT;
this.ball.moveY=[DIRECTION.UP, DIRECTION.DOWN][Math.round(Math.random())];
this.ball.y=Math.floor(Math.random() * this.canvas.height - 200) + 200;
this.turn=null;
}
// If the player collides with the bound limits, update the x and y coords.
if (this.player.y <=0) this.player.y=0;
else if (this.player.y >=(this.canvas.height - this.player.height)) this.player.y=(this.canvas.height - this.player.height);
// Move ball in intended direction based on moveY and moveX values
if (this.ball.moveY===DIRECTION.UP) this.ball.y -=(this.ball.speed / 1.5);
else if (this.ball.moveY===DIRECTION.DOWN) this.ball.y +=(this.ball.speed / 1.5);
if (this.ball.moveX===DIRECTION.LEFT) this.ball.x -=this.ball.speed;
else if (this.ball.moveX===DIRECTION.RIGHT) this.ball.x +=this.ball.speed;
// Handle paddle (AI) UP and DOWN movement
if (this.paddle.y > this.ball.y - (this.paddle.height / 2)) {
if (this.ball.moveX===DIRECTION.RIGHT) this.paddle.y -=this.paddle.speed / 1.5;
else this.paddle.y -=this.paddle.speed / 4;
}
if (this.paddle.y < this.ball.y - (this.paddle.height / 2)) {
if (this.ball.moveX===DIRECTION.RIGHT) this.paddle.y +=this.paddle.speed / 1.5;
else this.paddle.y +=this.paddle.speed / 4;
}
// Handle paddle (AI) wall collision
if (this.paddle.y >=this.canvas.height - this.paddle.height) this.paddle.y=this.canvas.height - this.paddle.height;
else if (this.paddle.y <=0) this.paddle.y=0;
// Handle Player-Ball collisions
if (this.ball.x - this.ball.width <=this.player.x && this.ball.x >=this.player.x - this.player.width) {
if (this.ball.y <=this.player.y + this.player.height && this.ball.y + this.ball.height >=this.player.y) {
this.ball.x=(this.player.x + this.ball.width);
this.ball.moveX=DIRECTION.RIGHT;
beep1.play();
}
}
// Handle paddle-ball collision
if (this.ball.x - this.ball.width <=this.paddle.x && this.ball.x >=this.paddle.x - this.paddle.width) {
if (this.ball.y <=this.paddle.y + this.paddle.height && this.ball.y + this.ball.height >=this.paddle.y) {
this.ball.x=(this.paddle.x - this.ball.width);
this.ball.moveX=DIRECTION.LEFT;
beep1.play();
}
}
}
// Handle the end of round transition
// Check to see if the player won the round.
if (this.player.score===rounds[this.round]) {
// Check to see if there are any more rounds/levels left and display the victory screen if
// there are not.
if (!rounds[this.round + 1]) {
this.over=true;
setTimeout(function () { Pong.endGameMenu('Winner!'); }, 1000);
} else {
// If there is another round, reset all the values and increment the round number.
this.color=this._generateRoundColor();
this.player.score=this.paddle.score=0;
this.player.speed +=0.5;
this.paddle.speed +=1;
this.ball.speed +=1;
this.round +=1;
beep3.play();
}
}
// Check to see if the paddle/AI has won the round.
else if (this.paddle.score===rounds[this.round]) {
this.over=true;
setTimeout(function () { Pong.endGameMenu('Game Over!'); }, 1000);
}
},
// Draw the objects to the canvas element
draw: function () {
// Clear the Canvas
this.context.clearRect(
0,
0,
this.canvas.width,
this.canvas.height
);
// Set the fill style to black
this.context.fillStyle=this.color;
// Draw the background
this.context.fillRect(
0,
0,
this.canvas.width,
this.canvas.height
);
// Set the fill style to white (For the paddles and the ball)
this.context.fillStyle='#ffffff';
// Draw the Player
this.context.fillRect(
this.player.x,
this.player.y,
this.player.width,
this.player.height
);
// Draw the Paddle
this.context.fillRect(
this.paddle.x,
this.paddle.y,
this.paddle.width,
this.paddle.height
);
// Draw the Ball
if (Pong._turnDelayIsOver.call(this)) {
this.context.fillRect(
this.ball.x,
this.ball.y,
this.ball.width,
this.ball.height
);
}
// Draw the net (Line in the middle)
this.context.beginPath();
this.context.setLineDash([7, 15]);
this.context.moveTo((this.canvas.width / 2), this.canvas.height - 140);
this.context.lineTo((this.canvas.width / 2), 140);
this.context.lineWidth=10;
this.context.strokeStyle='#ffffff';
this.context.stroke();
// Set the default canvas font and align it to the center
this.context.font='100px Courier New';
this.context.textAlign='center';
// Draw the players score (left)
this.context.fillText(
this.player.score.toString(),
(this.canvas.width / 2) - 300,
200
);
// Draw the paddles score (right)
this.context.fillText(
this.paddle.score.toString(),
(this.canvas.width / 2) + 300,
200
);
// Change the font size for the center score text
this.context.font='30px Courier New';
// Draw the winning score (center)
this.context.fillText(
'Round ' + (Pong.round + 1),
(this.canvas.width / 2),
35
);
// Change the font size for the center score value
this.context.font='40px Courier';
// Draw the current round number
this.context.fillText(
rounds[Pong.round] ? rounds[Pong.round] : rounds[Pong.round - 1],
(this.canvas.width / 2),
100
);
},
loop: function () {
Pong.update();
Pong.draw();
// If the game is not over, draw the next frame.
if (!Pong.over) requestAnimationFrame(Pong.loop);
},
listen: function () {
document.addEventListener('keydown', function (key) {
// Handle the 'Press any key to begin' function and start the game.
if (Pong.running===false) {
Pong.running=true;
window.requestAnimationFrame(Pong.loop);
}
// Handle up arrow and w key events
if (key.keyCode===38 || key.keyCode===87) Pong.player.move=DIRECTION.UP;
// Handle down arrow and s key events
if (key.keyCode===40 || key.keyCode===83) Pong.player.move=DIRECTION.DOWN;
});
// Stop the player from moving when there are no keys being pressed.
document.addEventListener('keyup', function (key) { Pong.player.move=DIRECTION.IDLE; });
},
// Reset the ball location, the player turns and set a delay before the next round begins.
_resetTurn: function(victor, loser) {
this.ball=Ball.new.call(this, this.ball.speed);
this.turn=loser;
this.timer=(new Date()).getTime();
victor.score++;
beep2.play();
},
// Wait for a delay to have passed after each turn.
_turnDelayIsOver: function() {
return ((new Date()).getTime() - this.timer >=1000);
},
// Select a random color as the background of each level/round.
_generateRoundColor: function () {
var newColor=colors[Math.floor(Math.random() * colors.length)];
if (newColor===this.color) return Pong._generateRoundColor();
return newColor;
}
};
var Pong=Object.assign({}, Game);
Pong.initialize();
</script>
</body>
</html>
本篇未完結,請繼續看下一篇:手把手教你7個有趣的JavaScript 項目-下「附源碼」
《JavaScript 使用 mediaDevices API 訪問攝像頭自拍》
*請認真填寫需求信息,我們會在24小時內與您取得聯系。