做代練網站能備案營銷網絡推廣哪家好
一、關于下載
1、文章中羅列了主要代碼,如需使用,請前往CSDN下載進行下載,包中包含所有文件素材,開箱即用
2、下載鏈接:https://download.csdn.net/download/zlxls/88305636
二、有這么一個需求
1、會場進行布局,需要設置布局包含的座位,桌子,設置在指定的位置,按照領導席位進行排布。
2、桌子可能時U型(四個開口方向)、圓形、方形。
3、根據每個座位序號設置水牌。
4、保存為圖片,方便直接打印,圖片為base64,可在服務端進行轉儲。
5、功能包括:新增位置、去除/恢復編輯樣式、門入口設置、投影設置、顯示/隱藏水牌、保存數據(數據保存時進行截圖,截圖格式為去除編輯樣式后的截圖)。
6、保存數據時,會將所有數據打包為json進行打印。
7、修改時,傳入初始化數據,會進行數據初始化。
8、包中包含所有文件素材,開箱即用。
9、文件包含一個index.html文件,為主文件。
10、index-base.html文件為原始拖動插件。
11、其他js、css等用到的插件已經全部打包,沒有文件遺漏。
12、本插件全部使用js+Jquery進行編寫,代碼沒有進行緊密封裝,可以根據自己需要進行修改和封裝,中間使用到的jquery選擇器比較多,但是主要功能操作都進行了注釋,方便讀者了解編寫時的邏輯,方便進行二次開發(fā)和修改。
12、如有疑問可聯系作者,歡迎指出bug和不足之處,以便完善內容。
三、實現的效果圖如下
四、主要邏輯代碼
<!DOCTYPE html>
<html lang="zh">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>會議室布局</title><link rel="stylesheet" type="text/css" href="css/bootstrap.css"><link rel="stylesheet" type="text/css" href="css/font-awesome.min.css"/><link rel="stylesheet" type="text/css" href="css/default.css"><link rel="stylesheet" type="text/css" href="css/gridstack.css"/><!--[if IE]><script src="js/html5.min.js"></script><![endif]-->
</head>
<body class="bgcolor-3">
<div class="jq22-container"><div class="jq22-content"><div class="container-top"><div class="btns"><div data-bind="click: add_new_widget" class="btn btn-primary">+ 新增一個位置(上限 <span class="add-span">0</span> 當前 <span class="add-span">0</span>)</div><div onclick="clear_style(this);" class="btn btn-warning clear_style">去除編輯樣式</div><div class="btn btn-default">門入口設置:</div><div class="btn btn-success door-op" data-type="0" data-index="0">上邊</div><div class="btn btn-success door-op" data-type="1" data-index="0">右邊</div><div class="btn btn-success door-op" data-type="2" data-index="0">下邊</div><div class="btn btn-success door-op" data-type="3" data-index="0">左邊</div><div class="btn btn-danger door-op" data-type="4" data-index="0">左移</div><div class="btn btn-danger door-op" data-type="5" data-index="0">右移</div><div class="btn btn-default">投影設置:</div><div class="btn btn-success door-op" data-type="0" data-index="1">上邊</div><div class="btn btn-success door-op" data-type="1" data-index="1">右邊</div><div class="btn btn-success door-op" data-type="2" data-index="1">下邊</div><div class="btn btn-success door-op" data-type="3" data-index="1">左邊</div><div class="btn btn-danger door-op" data-type="4" data-index="1">左移</div><div class="btn btn-danger door-op" data-type="5" data-index="1">右移</div><div onclick="submitHandler();" class="btn btn-success" style="float: right;">保存數據</div><div onclick="names_style(this);" class="btn btn-primary" style="float: right;">隱藏水牌</div></div><p class="tips" style="">請根據會場進行布局,位置按鈕可以拖拽放大縮小,上下位置,不能有空位,可使用隱藏功能占位</p></div><div id="container-data"><div class="names"></div><div class="container-fluid" style="padding: 15px;"><div data-bind="component: {name: 'dashboard-grid', params: $data}" class="template-base"></div><div class="door-ty door"><img src="img/door.png"></div><div class="door-ty ty"><img src="img/ty.png"></div></div></div></div>
</div>
<input name="id" type="hidden" value="">
<input name="type" type="hidden" value="">
<script src="js/jquery.min.js"></script>
<script src="js/jquery-ui.min.js"></script>
<script src="js/bootstrap.min.js"></script>
<script src="js/lodash.min.js"></script>
<script src="js/knockout-min.js"></script>
<script src="js/gridstack.js"></script>
<script src="js/html2canvas.min.js"></script>
<script src="layer/layer.min.js"></script>
<script type="text/javascript">//數據//格式:[{x: 0, y: 0, width: 1, height: 1, input: '姓名1', hide: '隱藏', class: '',rate:0}];var json = "";//數量var roomIdNum = "60";roomIdNum = parseInt(roomIdNum);$(".add-span").html(roomIdNum);//虛擬對齊顯示數量,用來美化頁面var roomIdNumYushu = roomIdNum % 10;var roomIdNumShow = roomIdNum+(roomIdNumYushu>0?(10-roomIdNumYushu):0);//操作類型var type = "0";//門、投影的位置//格式:[{"t":"bottom","t1":"0","l":"left","l1":"50"},{"t":"top","t1":"0","l":"left","l1":"50"}]//下標0為門位置1為投影位置var doors = "";//水牌//格式:['張三','李四']var names = "";//初始化組件相關參數ko.components.register('dashboard-grid', {viewModel: {createViewModel: function (controller, componentInfo) {var ViewModel = function (controller, componentInfo) {var grid = null;this.widgets = controller.widgets;this.afterAddWidget = function (items) {if (grid == null) {grid = $(componentInfo.element).find('.grid-stack').gridstack({auto: false}).data('gridstack');}var item = _.find(items, function (i) { return i.nodeType == 1 });grid.add_widget(item);ko.utils.domNodeDisposal.addDisposeCallback(item, function () {grid.remove_widget(item);});};};return new ViewModel(controller, componentInfo);}},template:['<div class="grid-stack" data-bind="foreach: {data: widgets, afterRender: afterAddWidget}">',' <div class="grid-stack-item" data-bind="attr: {\'data-input\': $data.input,\'data-class\': $data.class,\'data-hide\': $data.hide,\'data-rate\': $data.rate,\'data-gs-x\': $data.x, \'data-gs-y\': $data.y, \'data-gs-width\': $data.width, \'data-gs-height\': $data.height, \'data-gs-auto-position\': $data.auto_position}">',' <div class="grid-stack-item-content">' +' <input placeholder="未填寫序號或名稱">' +' <span class="grid-style-span">' +' <span data-type="0">?型</span>' +' <span data-type="1">u型</span>' +' <span data-type="2">?型</span>' +' <span data-type="3">∩型</span>' +' <span data-type="4">?型</span>' +' <span data-type="5">○型</span>' +' </span>' +' <span class="opacity-span"></span>' +' </div>' +' <button class="grid-stack-item-close" data-bind="click: $root.delete_widget"></button>',' </div>','</div> '].join('')});$(function () {//模塊形狀點擊事件$(".template-base").on('click','.grid-style-span span',function(){$(this).parent().parent().removeClass("grid-style-0").removeClass("grid-style-1").removeClass("grid-style-2").removeClass("grid-style-3").removeClass("grid-style-4").removeClass("grid-style-5").addClass("grid-style-"+$(this).data("type"));});//顯示或隱藏組件$(".template-base").on('click','.opacity-span',function(){if($(this).parent().hasClass("active")){$(this).parent().find(".grid-style-span").show();$(this).parent().find("input").removeClass("input-show");$(this).parent().removeClass("active");$(this).html("隱藏");}else{$(this).parent().find(".grid-style-span").hide();$(this).parent().find("input").addClass("input-show");$(this).parent().addClass("active");$(this).html("顯示");}getCount();});//初始化組件相關事件var Controller = function (widgets) {var self = this;this.widgets = ko.observableArray(widgets);//新增一個組件this.add_new_widget = function () {this.widgets.push({x: 0, y: 0, width: 1, height: 1, input:'', hide:'隱藏', rate:0, class:'', auto_position: true});getCount();};//刪除一個組件this.delete_widget = function (item) {self.widgets.remove(item);getCount();};};//初始數據初始化var widgets = [];if(json) {widgets = JSON.parse(json);//計算個數$(".add-span").eq(1).html(json.match(new RegExp(/\隱藏/g)).length);}var controller = new Controller(widgets);ko.applyBindings(controller);//門、投影的位置點擊事件setDoorOpClick();//門、投影的位置 初始化//延時加載,不然獲取的寬度不是數據初始化的寬度setTimeout(function () {initDoorOp();},500);//水牌 初始化initNames();});/*** 數據提交*/function submitHandler() {var serialized_data = _.map($('.grid-stack > .grid-stack-item:visible'), function (el) {el = $(el);var node = el.data('_gridstack_node');return {x : node.x, y : node.y, width : node.width, height : node.height, input : el.find("input").val(), hide : el.find(".opacity-span").html(), rate : getRateFlag(el), class : el.find(".grid-stack-item-content").hasClass("active")?'active':'',};}, this);if(serialized_data.length<1){layer.alert("請完善布局再提交");return false;}var count = serialized_data.length - $('.grid-stack > .grid-stack-item:visible > .active').length;if(count>roomIdNum){layer.alert("該會場容納人數最多為"+roomIdNum+",當前布局"+count);return false;}names = [];$("[name='names[]']").each(function () {names.push($(this).val());});var _data = {json : JSON.stringify(serialized_data),doors : JSON.stringify(doors),names : JSON.stringify(names),type : $("[name='type']").val(),id : $("[name='id']").val()};//begin截圖時要處理的問題//1、如果是編輯樣式,則去除var clear_style_flag = 0;if(!$(".template-base").hasClass("template-base-style")){clear_style(".clear_style");clear_style_flag = 1;}//2、輸入框的背景顏色去除$(".input-show").css("background","unset");//3、輸入框截圖存在錯位,需要動態(tài)替換為div標簽顯示$(".names-name").each(function () {$(this).find("div").html($(this).find("input").val());$(this).find("input").hide();$(this).find("div").show();});//endhtml2canvas(document.getElementById("container-data")).then(function(canvas) {//begin截圖后進行數據恢復//1、如果去除了編輯樣式,則恢復if(clear_style_flag == 1){clear_style(".clear_style");}//2、輸入框的背景顏色恢復$(".input-show").css("background","#18bc9c");//3、動態(tài)恢復為input標簽顯示$(".names-name").each(function () {$(this).find("input").show();$(this).find("div").hide();});//end_data.img = canvas.toDataURL("image/png");console.info(_data);return false;$.ajax({url: "http://localhost:8183/layout/editData",type: "post",dataType: "json",data:_data,success: function(result) {layer.alert(result.msg);}});});}/*** 計算組件個數*/function getCount() {var _count = $('.grid-stack > .grid-stack-item:visible').length - $('.grid-stack > .grid-stack-item:visible > .active').length;$(".add-span").eq(1).html(_count);}/*** 清楚組件編輯樣式*/function clear_style(_this) {if($(".template-base").hasClass("template-base-style")){$(".template-base").removeClass("template-base-style");$(_this).html("去除編輯樣式");$(".grid-stack-item-content input").attr("placeholder","未填寫序號或名稱");$(".names-name input").attr("placeholder","請輸入姓名");}else{$(".template-base").addClass("template-base-style");$(_this).html("恢復編輯樣式");$("input").removeAttr("placeholder");}}/*** 水牌名稱編輯樣式*/function names_style(_this) {if($(_this).html()=='隱藏水牌'){$(".names").hide();$(_this).html("顯示水牌");}else{$(".names").show();$(_this).html("隱藏水牌");}}/*** 獲取形狀編號* @param el* @returns {number}*/function getRateFlag(el) {if(el.find(".grid-stack-item-content").hasClass("grid-style-1")){return 1;}else if(el.find(".grid-stack-item-content").hasClass("grid-style-2")){return 2;}else if(el.find(".grid-stack-item-content").hasClass("grid-style-3")){return 3;}else if(el.find(".grid-stack-item-content").hasClass("grid-style-4")){return 4;}else if(el.find(".grid-stack-item-content").hasClass("grid-style-5")){return 5;}else{return 0;}}/*** 門和投影點擊事件*/function setDoorOpClick() {$(".door-op").on('click',function(){var numOne = 5;var type = parseInt($(this).data("type"));var index = parseInt($(this).data("index"));var indexBegin = getDoorOpIndexBegin(index);switch (type) {case 0:doors[index].t = "top"; doors[index].t1 = "0"; doors[index].l = "left"; doors[index].l1 = "50";break;//上case 1:doors[index].t = "right"; doors[index].t1 = "0"; doors[index].l = "top"; doors[index].l1 = "50";break;//右case 2:doors[index].t = "bottom"; doors[index].t1 = "0"; doors[index].l = "left"; doors[index].l1 = "50";break;//下case 3:doors[index].t = "left"; doors[index].t1 = "0"; doors[index].l = "top"; doors[index].l1 = "50";break;//左case 4://左移 上移var _val = parseInt(doors[index].l1)-numOne;doors[index].l1 = _val<=0?0:_val;break;default://右移 下移var _val = parseInt(doors[index].l1)+numOne;doors[index].l1 = _val>=100?100:_val;break;}setDoorOpStyle();});}/*** 門和投影移動方向*/function setDoorOpStyle() {setDoorOp(0);setDoorOp(1);//獲取當前方向標簽的長度或者高度var max0 = getDoorOpStyleMax(0);var max1 = getDoorOpStyleMax(1);//計算當前比例下的實際定位長度或者高度var aspect0 = (max0/100)*parseInt(doors[0].l1);var aspect1 = (max1/100)*parseInt(doors[1].l1);//當前定位方向var position0 = doors[0].l;var position1 = doors[1].l;//如果為左側定位&&定位數值為100%時,換為右側定位&&數值為0%if(doors[0].l=='left' && parseFloat(doors[0].l1)==100){aspect0 = 0;position0 = 'right';}if(doors[1].l=='left' && parseFloat(doors[1].l1)==100){aspect1 = 0;position1 = 'right';}$(".door").css("top","unset").css("left","unset").css("right","unset").css("bottom","unset").css(doors[0].t,doors[0].t1+"px").css(position0,aspect0+"px");$(".ty" ).css("top","unset").css("left","unset").css("right","unset").css("bottom","unset").css(doors[1].t,doors[1].t1+"px").css(position1,aspect1+"px");}/*** 門和投影選擇器* @param _index* @returns {number}*/function getDoorOpIndexBegin(_index){return 6*(_index+1);}/*** 門和投影寫入操作* @param _index*/function setDoorOp(_index){if(doors[_index].t == "top"||doors[_index].t == "bottom"){$(".door-op").eq(getDoorOpIndexBegin(_index)-2).html("左移");$(".door-op").eq(getDoorOpIndexBegin(_index)-1).html("右移");}else{$(".door-op").eq(getDoorOpIndexBegin(_index)-2).html("上移");$(".door-op").eq(getDoorOpIndexBegin(_index)-1).html("下移");}}/*** 門和投影獲取實際長了寬* @param _index* @returns {jQuery}*/function getDoorOpStyleMax(_index) {if(doors[_index].t == "top"||doors[_index].t == "bottom"){return $(".container-fluid").width();}else{return $(".container-fluid").height();}}/*** 門、投影的位置 初始化*/function initDoorOp(){if(doors && $.isArray(JSON.parse(doors))) {doors = JSON.parse(doors);}else{doors = [{"t":"bottom","t1":"0","l":"left","l1":"50"},{"t":"top","t1":"0","l":"left","l1":"50"}];}setDoorOpStyle();}/*** 水牌 初始化* 由于容納人數roomIdNum是動態(tài)的,* 這里需要動態(tài)處理已有的水牌數據,* 例如原本容納人數為20人,修改時可能變成15人或者25人,* 要以實際能容納的人數為基準。*/function initNames(){var _names = names?JSON.parse(names):[];names = [];for (var i=0;i<roomIdNumShow;i++){names.push(_names.length>i?_names[i]:"");}setNames();}/*** 水牌名稱設置*/function setNames() {var html = "";for (var i=0;i<names.length;i++){if(i<roomIdNum){html+='<div class="names-row"><div class="names-index">'+(i+1)+'</div><div class="names-name"><div style="display: none;"></div><input name="names[]" value="'+names[i]+'" placeholder="請輸入姓名"></div></div>';}else{//補齊一排的樣式,必然比較難看html+='<div class="names-row"><div class="names-index"></div><div class="names-name"></div></div>';}}$(".names").html(html);}
</script>
</body>
</html>