关于移动手机端富文本编辑器qeditor图片上传改造

  日前项目需要在移动端增加富文本编辑,上网找了下,大多数都是针对pc版的,不太兼容手机,当然由于手机屏幕小等原因也限制富文本编辑器的众多强大功能,所以要找的编辑器功能必须是精简的。

  找了好久,发现qeditor比较精简,操作简单,唯一缺点是上传图片时只能填写url,不能直接从手机上传。

  针对这点,自己决定动手修改。

  修改思路:

    1、创建文件上传输入框

    2、点击编辑器上传图片按钮时,触发文件输入框点击事件

    3、选择图片后异步上传至服务器,返回图片路径

    4、编辑器插入img标签,显示图片

  

  以下是修改过程:

  上图了解下原来是怎么样的,这个是qeditor的界面,qeditor的样式可以自己修改:

  

  点击上传图片按钮后是弹框要求输入图片url的 :

  

  以下是改造后的效果,点击图片上传按钮显示的是现在手机相册图片 :

 

  选择后上传图片:

 

  qeditor的代码只有200多行,相当简洁,以下是原始代码:

// Generated by CoffeeScript 1.6.3
/*
jquery.qeditor
==============This is a simple WYSIWYG editor with jQuery.## Author:Jason Lee <huacnlee@gmail.com>## Requirements:[jQuery](http://jquery.com)(Font-Awesome)[http://fortawesome.github.io/Font-Awesome/] - Toolbar icons## Usage:$("textarea").qeditor();and then you need filt the html tags,attributes in you content page.
In Rails application, you can use like this:<%= sanitize(@post.body,:tags => %w(strong b i u strike ol ul li address blockquote pre code br div p), :attributes => %w(src)) %>
*/var QEDITOR_ALLOW_TAGS_ON_PASTE, QEDITOR_DISABLE_ATTRIBUTES_ON_PASTE, QEDITOR_TOOLBAR_HTML;QEDITOR_TOOLBAR_HTML = "<div class=\"qeditor_toolbar\">\n  <a href=\"#\" data-action=\"bold\" class=\"qe-bold\"><span class=\"fa fa-bold\" title=\"Bold\"></span></a> \n  <a href=\"#\" data-action=\"italic\" class=\"qe-italic\"><span class=\"fa fa-italic\" title=\"Italic\"></span></a> \n  <a href=\"#\" data-action=\"underline\" class=\"qe-underline\"><span class=\"fa fa-underline\" title=\"Underline\"></span></a> \n  <a href=\"#\" data-action=\"strikethrough\" class=\"qe-strikethrough\"><span class=\"fa fa-strikethrough\" title=\"Strike-through\"></span></a>         \n  <span class=\"vline\"></span>\n  <span class=\"qe-icon qe-heading\">\n    <ul class=\"qe-menu\">\n      <li><a href=\"#\" data-name=\"h1\" class=\"qe-h1\">Heading 1</a></li>\n      <li><a href=\"#\" data-name=\"h2\" class=\"qe-h2\">Heading 2</a></li>\n      <li><a href=\"#\" data-name=\"h3\" class=\"qe-h3\">Heading 3</a></li>\n      <li><a href=\"#\" data-name=\"h4\" class=\"qe-h4\">Heading 4</a></li>\n      <li><a href=\"#\" data-name=\"h5\" class=\"qe-h5\">Heading 5</a></li>\n      <li><a href=\"#\" data-name=\"h6\" class=\"qe-h6\">Heading 6</a></li>\n      <li class=\"qe-hline\"></li>\n      <li><a href=\"#\" data-name=\"p\" class=\"qe-p\">Paragraph</a></li>\n    </ul>\n    <span class=\"icon fa fa-font\"></span>\n  </span>\n  <span class=\"vline\"></span>\n  <a href=\"#\" data-action=\"insertorderedlist\" class=\"qe-ol\"><span class=\"fa fa-list-ol\" title=\"Insert Ordered-list\"></span></a> \n  <a href=\"#\" data-action=\"insertunorderedlist\" class=\"qe-ul\"><span class=\"fa fa-list-ul\" title=\"Insert Unordered-list\"></span></a> \n  <a href=\"#\" data-action=\"indent\" class=\"qe-indent\"><span class=\"fa fa-indent\" title=\"Indent\"></span></a> \n  <a href=\"#\" data-action=\"outdent\" class=\"qe-outdent\"><span class=\"fa fa-outdent\" title=\"Outdent\"></span></a> \n  <span class=\"vline\"></span> \n  <a href=\"#\" data-action=\"insertHorizontalRule\" class=\"qe-hr\"><span class=\"fa fa-minus\" title=\"Insert Horizontal Rule\"></span></a> \n  <a href=\"#\" data-action=\"blockquote\" class=\"qe-blockquote\"><span class=\"fa fa-quote-left\" title=\"Blockquote\"></span></a> \n  <a href=\"#\" data-action=\"pre\" class=\"qe-pre\"><span class=\"fa fa-code\" title=\"Pre\"></span></a> \n  <a href=\"#\" data-action=\"createLink\" class=\"qe-link\"><span class=\"fa fa-link\" title=\"Create Link\" title=\"Create Link\"></span></a> \n  <a href=\"#\" data-action=\"insertimage\" class=\"qe-image\"><span class=\"fa fa-picture-o\" title=\"Insert Image\"></span></a> \n  <a href=\"#\" οnclick=\"return QEditor.toggleFullScreen(this);\" class=\"qe-fullscreen pull-right\"><span class=\"fa fa-arrows-alt\" title=\"Toggle Fullscreen\"></span></a> \n</div>";QEDITOR_ALLOW_TAGS_ON_PASTE = "div,p,ul,ol,li,hr,br,b,strong,i,em,img,h2,h3,h4,h5,h6,h7";QEDITOR_DISABLE_ATTRIBUTES_ON_PASTE = ["style", "class", "id", "name", "width", "height"];window.QEditor = {actions: ['bold', 'italic', 'underline', 'strikethrough', 'insertunorderedlist', 'insertorderedlist', 'blockquote', 'pre'],action: function(el, a, p) {var editor;editor = $(".qeditor_preview", $(el).parent().parent());editor.find(".qeditor_placeholder").remove();editor.focus();if (p === null) {p = false;}if (a === "blockquote" || a === "pre") {p = a;a = "formatBlock";}if (a === "createLink") {p = prompt("Type URL:");if (p.trim().length === 0) {return false;}} else if (a === "insertimage") {p = prompt("Image URL:");if (p.trim().length === 0) {return false;}}if (QEditor.state(a)) {document.execCommand(a, false, null);} else {document.execCommand(a, false, p);}QEditor.checkSectionState(editor);editor.change();return false;},state: function(action) {return document.queryCommandState(action) === true;},prompt: function(title) {var val;val = prompt(title);if (val) {return val;} else {return false;}},toggleFullScreen: function(el) {var border;border = $(el).parent().parent();if (border.data("qe-fullscreen") === "1") {QEditor.exitFullScreen();} else {QEditor.enterFullScreen(border);}return false;},enterFullScreen: function(border) {border.data("qe-fullscreen", "1").addClass("qeditor_fullscreen");border.find(".qeditor_preview").focus();return border.find(".qe-fullscreen span").attr("class", "fa fa-compress");},exitFullScreen: function() {return $(".qeditor_border").removeClass("qeditor_fullscreen").data("qe-fullscreen", "0").find(".qe-fullscreen span").attr("class", "fa fa-arrows-alt");},getCurrentContainerNode: function() {var containerNode, node;if (window.getSelection) {node = window.getSelection().anchorNode;containerNode = node.nodeType === 3 ? node.parentNode : node;}return containerNode;},checkSectionState: function(editor) {var a, link, _i, _len, _ref, _results;_ref = QEditor.actions;_results = [];for (_i = 0, _len = _ref.length; _i < _len; _i++) {a = _ref[_i];link = editor.parent().find(".qeditor_toolbar a[data-action=" + a + "]");if (QEditor.state(a)) {_results.push(link.addClass("qe-state-on"));} else {_results.push(link.removeClass("qe-state-on"));}}return _results;},version: function() {return "0.2.0";}
};(function($) {return $.fn.qeditor = function(options) {return this.each(function() {var currentVal, editor, obj, placeholder, qe_heading, toolbar;obj = $(this);obj.addClass("qeditor");editor = $('<div class="qeditor_preview clearfix" contentEditable="true"></div>');placeholder = $('<div class="qeditor_placeholder"></div>');$(document).keyup(function(e) {if (e.keyCode === 27) {return QEditor.exitFullScreen();}});document.execCommand('defaultParagraphSeparator', false, 'p');currentVal = obj.val();editor.html(currentVal);editor.addClass(obj.attr("class"));obj.after(editor);placeholder.text(obj.attr("placeholder"));editor.attr("placeholder", obj.attr("placeholder") || "");editor.append(placeholder);editor.focusin(function() {QEditor.checkSectionState(editor);return $(this).find(".qeditor_placeholder").remove();});editor.blur(function() {var t;t = $(this);QEditor.checkSectionState(editor);if (t.html().length === 0 || t.html() === "<br>" || t.html() === "<p></p>") {return $(this).html('<div class="qeditor_placeholder">' + $(this).attr("placeholder") + '</div>');}});editor.change(function() {var pobj, t;pobj = $(this);t = pobj.parent().find('.qeditor');return t.val(pobj.html());});editor.on("paste", function() {var txt;txt = $(this);return setTimeout(function() {var attrName, els, _i, _len;els = txt.find("*");for (_i = 0, _len = QEDITOR_DISABLE_ATTRIBUTES_ON_PASTE.length; _i < _len; _i++) {attrName = QEDITOR_DISABLE_ATTRIBUTES_ON_PASTE[_i];els.removeAttr(attrName);}els.find(":not(" + QEDITOR_ALLOW_TAGS_ON_PASTE + ")").contents().unwrap();txt.change();return true;}, 100);});editor.keyup(function(e) {QEditor.checkSectionState(editor);return $(this).change();});editor.on("click", function(e) {QEditor.checkSectionState(editor);return e.stopPropagation();});editor.keydown(function(e) {var node, nodeName;node = QEditor.getCurrentContainerNode();nodeName = "";if (node && node.nodeName) {nodeName = node.nodeName.toLowerCase();}if (e.keyCode === 13 && !(e.shiftKey || e.ctrlKey)) {if (nodeName === "blockquote" || nodeName === "pre") {e.stopPropagation();document.execCommand('InsertParagraph', false);document.execCommand("formatBlock", false, "p");document.execCommand('outdent', false);return false;}}});obj.hide();obj.wrap('<div class="qeditor_border"></div>');obj.after(editor);toolbar = $(QEDITOR_TOOLBAR_HTML);qe_heading = toolbar.find(".qe-heading");qe_heading.mouseenter(function() {$(this).addClass("hover");return $(this).find(".qe-menu").show();});qe_heading.mouseleave(function() {$(this).removeClass("hover");return $(this).find(".qe-menu").hide();});toolbar.find(".qe-heading .qe-menu a").click(function() {var link;link = $(this);link.parent().parent().hide();QEditor.action(this, "formatBlock", link.data("name"));return false;});toolbar.find("a[data-action]").click(function() {return QEditor.action(this, $(this).attr("data-action"));});return editor.before(toolbar);});};
})(jQuery);
View Code

  修改完成后的代码:

// Generated by CoffeeScript 1.6.3
/*
jquery.qeditor
==============This is a simple WYSIWYG editor with jQuery.## Author:Jason Lee <huacnlee@gmail.com>## Requirements:[jQuery](http://jquery.com)(Font-Awesome)[http://fortawesome.github.io/Font-Awesome/] - Toolbar icons## Usage:$("textarea").qeditor();and then you need filt the html tags,attributes in you content page.
In Rails application, you can use like this:<%= sanitize(@post.body,:tags => %w(strong b i u strike ol ul li address blockquote pre code br div p), :attributes => %w(src)) %>
*/var QEDITOR_ALLOW_TAGS_ON_PASTE, QEDITOR_DISABLE_ATTRIBUTES_ON_PASTE, QEDITOR_TOOLBAR_HTML;QEDITOR_TOOLBAR_HTML = "<div class=\"qeditor_toolbar\">\n  <a href=\"#\" data-action=\"bold\" class=\"qe-bold\"><span class=\"fa fa-bold\" title=\"Bold\"></span></a> \n  <a href=\"#\" data-action=\"italic\" class=\"qe-italic\"><span class=\"fa fa-italic\" title=\"Italic\"></span></a> \n  <a href=\"#\" data-action=\"underline\" class=\"qe-underline\"><span class=\"fa fa-underline\" title=\"Underline\"></span></a> \n  <a href=\"#\" data-action=\"strikethrough\" class=\"qe-strikethrough\"><span class=\"fa fa-strikethrough\" title=\"Strike-through\"></span></a>         \n  <span class=\"vline\"></span>\n  <span class=\"qe-icon qe-heading\">\n    <ul class=\"qe-menu\">\n      <li><a href=\"#\" data-name=\"h1\" class=\"qe-h1\">Heading 1</a></li>\n      <li><a href=\"#\" data-name=\"h2\" class=\"qe-h2\">Heading 2</a></li>\n      <li><a href=\"#\" data-name=\"h3\" class=\"qe-h3\">Heading 3</a></li>\n      <li><a href=\"#\" data-name=\"h4\" class=\"qe-h4\">Heading 4</a></li>\n      <li><a href=\"#\" data-name=\"h5\" class=\"qe-h5\">Heading 5</a></li>\n      <li><a href=\"#\" data-name=\"h6\" class=\"qe-h6\">Heading 6</a></li>\n      <li class=\"qe-hline\"></li>\n      <li><a href=\"#\" data-name=\"p\" class=\"qe-p\">Paragraph</a></li>\n    </ul>\n    <span class=\"icon fa fa-font\"></span>\n  </span>\n  <span class=\"vline\"></span>\n  <a href=\"#\" data-action=\"insertorderedlist\" class=\"qe-ol\"><span class=\"fa fa-list-ol\" title=\"Insert Ordered-list\"></span></a> \n  <a href=\"#\" data-action=\"insertunorderedlist\" class=\"qe-ul\"><span class=\"fa fa-list-ul\" title=\"Insert Unordered-list\"></span></a> \n  <a href=\"#\" data-action=\"indent\" class=\"qe-indent\"><span class=\"fa fa-indent\" title=\"Indent\"></span></a> \n  <a href=\"#\" data-action=\"outdent\" class=\"qe-outdent\"><span class=\"fa fa-outdent\" title=\"Outdent\"></span></a> \n  <span class=\"vline\"></span> \n  <a href=\"#\" data-action=\"insertHorizontalRule\" class=\"qe-hr\"><span class=\"fa fa-minus\" title=\"Insert Horizontal Rule\"></span></a> \n  <a href=\"#\" data-action=\"blockquote\" class=\"qe-blockquote\"><span class=\"fa fa-quote-left\" title=\"Blockquote\"></span></a> \n  <a href=\"#\" data-action=\"pre\" class=\"qe-pre\"><span class=\"fa fa-code\" title=\"Pre\"></span></a> \n  <a href=\"#\" data-action=\"createLink\" class=\"qe-link\"><span class=\"fa fa-link\" title=\"Create Link\" title=\"Create Link\"></span></a> \n  <a href=\"#\" data-action=\"insertimage\" class=\"qe-image\"><span class=\"fa fa-picture-o\" title=\"Insert Image\"></span></a> \n <a href=\"#\" οnclick=\"return QEditor.toggleFullScreen(this);\" class=\"qe-fullscreen pull-right\"><span class=\"fa fa-arrows-alt\" title=\"Toggle Fullscreen\"></span></a> \n</div>";QEDITOR_ALLOW_TAGS_ON_PASTE = "div,p,ul,ol,li,hr,br,b,strong,i,em,img,h2,h3,h4,h5,h6,h7";QEDITOR_DISABLE_ATTRIBUTES_ON_PASTE = ["style", "class", "id", "name", "width", "height"];window.QEditor = {actions: ['bold', 'italic', 'underline', 'strikethrough', 'insertunorderedlist', 'insertorderedlist', 'blockquote', 'pre'],action: function(el, a, p) {var editor;editor = $(".qeditor_preview", $(el).parent().parent());editor.find(".qeditor_placeholder").remove();editor.focus();if (p === null) {p = false;}if (a === "blockquote" || a === "pre") {p = a;a = "formatBlock";}if (a === "createLink") {p = prompt("Type URL:");if (p.trim().length === 0) {return false;}} else if (a === "insertimage") {//p = prompt("Image URL:");//TODOvar input;if(document.getElementById('inImgId')){input = document.getElementById('inImgId');}else{input = document.createElement('input');input.setAttribute('id', 'inImgId');input.setAttribute('type', 'file');input.setAttribute('name', 'file');input.setAttribute('accept', 'image/gif, image/jpeg, image/jpg, image/png');document.body.appendChild(input);input.style.display = 'none';}input.click();input.onchange = function(){if(!input.value){return;}var fd = new FormData();var file;file = input.files[0];fd.append('file', file);$.ajax({url : window.location.protocol + '//' + window.location.host + '/weixin/uploadArticlePic',data : fd,processData : false,contentType : false,enctype : 'multipart/form-data',type : 'POST',success : function(data) {var json = JSON.parse(data);if (json.success) {QEditor.imageChange(json.data);} else {alert(json.message);}}});}if (p == null || p.trim().length === 0) {return false;}}if (QEditor.state(a)) {document.execCommand(a, false, null);} else {document.execCommand(a, false, p);}QEditor.checkSectionState(editor);editor.change();return false;},state: function(action) {return document.queryCommandState(action) === true;},prompt: function(title) {var val;val = prompt(title);if (val) {return val;} else {return false;}},toggleFullScreen: function(el) {var border;border = $(el).parent().parent();if (border.data("qe-fullscreen") === "1") {QEditor.exitFullScreen();} else {QEditor.enterFullScreen(border);}return false;},enterFullScreen: function(border) {border.data("qe-fullscreen", "1").addClass("qeditor_fullscreen");border.find(".qeditor_preview").focus();return border.find(".qe-fullscreen span").attr("class", "fa fa-compress");},exitFullScreen: function() {return $(".qeditor_border").removeClass("qeditor_fullscreen").data("qe-fullscreen", "0").find(".qe-fullscreen span").attr("class", "fa fa-arrows-alt");},getCurrentContainerNode: function() {var containerNode, node;if (window.getSelection) {node = window.getSelection().anchorNode;containerNode = node.nodeType === 3 ? node.parentNode : node;}return containerNode;},checkSectionState: function(editor) {var a, link, _i, _len, _ref, _results;_ref = QEditor.actions;_results = [];for (_i = 0, _len = _ref.length; _i < _len; _i++) {a = _ref[_i];link = editor.parent().find(".qeditor_toolbar a[data-action=" + a + "]");if (QEditor.state(a)) {_results.push(link.addClass("qe-state-on"));} else {_results.push(link.removeClass("qe-state-on"));}}return _results;},imageChange: function(imgUrl) {var editor = $(".qeditor_preview", $(".qeditor_border"));editor.focus();document.execCommand("insertimage", false, imgUrl);QEditor.checkSectionState(editor);editor.change();},version: function() {return "0.2.0";}
};(function($) {return $.fn.qeditor = function(params) {// 控制上传图片按钮显示与否 Add by C.Q 20160803var defaults = {showImage: true // true:显示上传图片按钮;false:不显示
    };params = $.extend({}, defaults, params);return this.each(function() {var currentVal, editor, obj, placeholder, qe_heading, toolbar;obj = $(this);obj.addClass("qeditor");editor = $('<div class="qeditor_preview clearfix" contentEditable="true"></div>');placeholder = $('<div class="qeditor_placeholder"></div>');$(document).keyup(function(e) {if (e.keyCode === 27) {return QEditor.exitFullScreen();}});document.execCommand('defaultParagraphSeparator', false, 'p');currentVal = obj.val();editor.html(currentVal);editor.addClass(obj.attr("class"));obj.after(editor);placeholder.text(obj.attr("placeholder"));editor.attr("placeholder", obj.attr("placeholder") || "");editor.append(placeholder);editor.focusin(function() {QEditor.checkSectionState(editor);return $(this).find(".qeditor_placeholder").remove();});editor.blur(function() {var t;t = $(this);QEditor.checkSectionState(editor);if (t.html().length === 0 || t.html() === "<br>" || t.html() === "<p></p>") {return $(this).html('<div class="qeditor_placeholder">' + $(this).attr("placeholder") + '</div>');}});editor.change(function() {var pobj, t;pobj = $(this);t = pobj.parent().find('.qeditor');return t.val(pobj.html());});editor.on("paste", function() {var txt;txt = $(this);return setTimeout(function() {var attrName, els, _i, _len;els = txt.find("*");for (_i = 0, _len = QEDITOR_DISABLE_ATTRIBUTES_ON_PASTE.length; _i < _len; _i++) {attrName = QEDITOR_DISABLE_ATTRIBUTES_ON_PASTE[_i];els.removeAttr(attrName);}els.find(":not(" + QEDITOR_ALLOW_TAGS_ON_PASTE + ")").contents().unwrap();txt.change();return true;}, 100);});editor.keyup(function(e) {QEditor.checkSectionState(editor);return $(this).change();});editor.on("click", function(e) {QEditor.checkSectionState(editor);return e.stopPropagation();});editor.keydown(function(e) {var node, nodeName;node = QEditor.getCurrentContainerNode();nodeName = "";if (node && node.nodeName) {nodeName = node.nodeName.toLowerCase();}if (e.keyCode === 13 && !(e.shiftKey || e.ctrlKey)) {if (nodeName === "blockquote" || nodeName === "pre") {e.stopPropagation();document.execCommand('InsertParagraph', false);document.execCommand("formatBlock", false, "p");document.execCommand('outdent', false);return false;}}});obj.hide();obj.wrap('<div class="qeditor_border"></div>');obj.after(editor);// 控制图片显示与否 Add by C.Q 20160803if (params.showImage == false) {QEDITOR_TOOLBAR_HTML = QEDITOR_TOOLBAR_HTML.replace('<a href="#" data-action="insertimage" class="qe-image"><span class="fa fa-picture-o" title="Insert Image"></span></a>', "");}toolbar = $(QEDITOR_TOOLBAR_HTML);qe_heading = toolbar.find(".qe-heading");qe_heading.mouseenter(function() {$(this).addClass("hover");return $(this).find(".qe-menu").show();});qe_heading.mouseleave(function() {$(this).removeClass("hover");return $(this).find(".qe-menu").hide();});toolbar.find(".qe-heading .qe-menu a").click(function() {var link;link = $(this);link.parent().parent().hide();QEditor.action(this, "formatBlock", link.data("name"));return false;});toolbar.find("a[data-action]").click(function() {return QEditor.action(this, $(this).attr("data-action"));});return editor.before(toolbar);});};
})(jQuery);
View Code

  在这里我就不解读其它的代码功能了,主要讲解下修改部分:

  1、在window.QEditor的action方法中有一处判断是否点击图片上传按钮的

else if (a === "insertimage") {p = prompt("Image URL:");if (p.trim().length === 0) {return false;}}

  从这里入手,根据思路进行相应改造

else if (a === "insertimage") {//p = prompt("Image URL:");var input;if(document.getElementById('inImgId')){input = document.getElementById('inImgId');}else{input = document.createElement('input');input.setAttribute('id', 'inImgId');input.setAttribute('type', 'file');input.setAttribute('name', 'file');input.setAttribute('accept', 'image/gif, image/jpeg, image/jpg, image/png');document.body.appendChild(input);input.style.display = 'none';}input.click();input.onchange = function(){if(!input.value){return;}var fd = new FormData();var file;file = input.files[0];fd.append('file', file);$.ajax({url : window.location.protocol + '//' + window.location.host + '/weixin/uploadArticlePic',data : fd,processData : false,contentType : false,enctype : 'multipart/form-data',type : 'POST',success : function(data) {var json = JSON.parse(data);if (json.success) {QEditor.imageChange(json.data);} else {alert(json.message);}}});}if (p == null || p.trim().length === 0) {return false;}}

注意到代码中上传图片成功后执行的 QEditor.imageChange(json.data)方法。

 这是我加上去的,目的是使编辑器插入图片,并改变编辑器的值(注意qeditor是由textarea和预览div组成,插入图片是插入到预览div中,并不存在textarea中,而取值却是从textarea中取,所以原作者以增加change()方法解决此问题,本人加入的QEditor.imageChange(json.data)同样是为解决这个问题)

imageChange: function(imgUrl) {var editor = $(".qeditor_preview", $(".qeditor_border"));editor.focus();document.execCommand("insertimage", false, imgUrl);QEditor.checkSectionState(editor);editor.change();}

至此修改完毕。

经测试。。。。

出现各种各样问题。。。。。图片旋转的、ip4拍照闪退、图片过大等。。。

后续优化:

  1、加入图片压缩,减少服务器带宽压力

  2、解决图片旋转问题

  3、加入进度条

  4、等

 

转载于:https://www.cnblogs.com/theroad/p/5736201.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/457486.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java IO 系统

Java IO系统 File类 用来处理文件目录&#xff0c;既可以代表一个特定文件的名称&#xff0c;也可以代表一组文件的名称&#xff0c;如果代表的是一个文件组&#xff0c;可以调用File.list()方法返回一个字符数组。 list()不传递任何参数时返回该目录下所有文件或文件名的字…

javascript/jquery高度宽度详情解说分析

为什么80%的码农都做不了架构师&#xff1f;>>> 一、window对象表示浏览器中打开的窗口 二、window对象可以省略 一、document对象是window对象的一部分 二、浏览器的HTML文档成为Document对象 window.location和document.location window对象的location属性引用的…

红黑树插入时的自平衡

红黑树插入时的自平衡 红黑树实质上是一棵自平衡的二叉查找树&#xff0c;引入带颜色的节点也是为了方便在进行插入或删除操作时&#xff0c;如果破坏了二叉查找树的平衡性能通过一系列变换保持平衡。 红黑树的性质 每个节点要么是红色&#xff0c;要么是黑色根节点必须是黑…

UWP学习记录

微软{X:Bind}、{Binding}资料网站 &#xff1a; https://msdn.microsoft.com/windows/uwp/xaml-platform/x-bind-markup-extension在View的ItemTemplate中绑定ViewModel的方法&#xff1a;1 <ItemsControl Name"XX" ItemsSource"{x:Bind VM.XXModels,ModeOne…

【Java】HashMap源码(1.7)

Life is not a ridiculous number of life, the meaning of life lies in life itself HashMap源码 散列集 数组和链表可以保持元素插入的顺序&#xff0c;对数组来说&#xff0c;他的优点是拥有连续的存储空间&#xff0c;因此可以使用元素下标快速访问&#xff0c;但缺点在…

画刷的使用

1.画刷的定义&#xff1a; HBRUSH hBrush; windows 自定义的画刷&#xff1a; WHITE_BRUSH、LTGRAY_BRUSH、GRAY_BRUSH、DKGRAY_BRUSH、BLACK_BRUSH和NULL_BRUSH &#xff08;也叫HOLLOW_BRUSH&#xff09; 获取方法如下&#xff1a; hBrush (HBRUSH) GetStockObject (GRAY_BR…

runtime官方文档

OC是一种面向对象的动态语言&#xff0c;作为初学者可能大多数人对面向对象这个概念理解的比较深&#xff0c;而对OC是动态语言这一特性了解的比较少。那么什么是动态语言&#xff1f;动态语言就是在运行时来执行静态语言的编译链接的工作。这就要求除了编译器之外还要有一种运…

【Java】synchronized关键字笔记

Java Synchronized 关键字 壹. Java并发编程存在的问题 1. 可见性问题 可见性问题是指一个线程不能立刻拿到另外一个线程对共享变量的修改的结果。 如&#xff1a; package Note.concurrency;public class Demo07 {private static boolean s true;public static void mai…

SQL Server-数据类型(七)

前言 前面几篇文章我们讲解了索引有关知识&#xff0c;这一节我们再继续我们下面内容讲解&#xff0c;简短的内容&#xff0c;深入的理解&#xff0c;Always to review the basics。 数据类型 SQL Server支持两种字符数据类型&#xff0c;一种是常规&#xff0c;另外一种则是Un…

pb retrieve时停止工作_大佬们挂在嘴边的PE、PB是什么?

在紧锣密鼓地准备科创50ETF的发行工作间隙&#xff0c;今天小夏先带你读懂最简单的PE、PB估值指标这两大指标。01、什么是PE&#xff08;市盈率&#xff09;PE&#xff0c;也就是市价盈利比率&#xff0c;简称市盈率。市盈率是指股票价格与每股收益&#xff08;每股收益&#x…

【设计模式 01】简单工厂模式(Simple factory pattern)

简单工厂模式 可以根据参数的不同返回不同类的实例 参考&#xff1a; CSDN|简单工厂模式 简单工厂通过传给工厂类的参数的不同&#xff0c;返回不同的对象&#xff0c;包括三部分组成&#xff1a; 具体的”产品“工厂类&#xff08;实例化并返回”产品“&#xff09;客户端&am…

用Visual Studio 2019连接 WSL来编译调试C/C++项目

因为有作业要在Linux环境下写&#xff0c;用虚拟机直接卡成PPT&#xff0c;VS code又不会调试&#xff0c;就搞一下VS 2019吧。 环境 windows 10 WSL(Ubuntu 18.04.4) Visual Studio Community 2019 Linux 里要有C/C环境&#xff08;gcc等&#xff09;VS要有 适用于 Linux…

系统移植的四大步骤

最近在学习系统移植的相关知识&#xff0c;在学习和调试过程中&#xff0c;发现了很多问题&#xff0c;也解决了很多问题&#xff0c;但总是对于我们的开发结果有一种莫名其妙的感觉&#xff0c;纠其原因&#xff0c;主要对于我们的开发环境没有一个深刻的认识&#xff0c;有时…

display:flex

flex&#xff1a;弹性布局 常用属性介绍&#xff1a; flex-direction: column &#xff08;设置主容器主轴方向&#xff09; flex-flow: row wrap &#xff08;第一个参数为flex-direction&#xff0c;第二个为flex-wrap&#xff09; align-items: flex-start &#xff08;设…

Linux(Ubuntu 19.10)下 Qt5 连接 MySQL(QMYSQL driver not loaded)

Linux&#xff08;Ubuntu 19.10&#xff09;下 Qt5 连接 MySQL 安装好 MySQL 和 Qt Qt 连接 MySQL 的代码 QSqlDatabase dQSqlDatabase::addDatabase("QMYSQL");//加载mysql驱动&#xff0c;这个字符串是固定的 d.setHostName("127.0.0.1"); d.setDatabas…

Wpf 数据绑定简介、实例1

简介&#xff1a;1.WPF绑定使用的源属性必须是依赖项属性&#xff0c;这是因为依赖项属性具有内置的更改通知支持&#xff0c;元素绑定表达式使用了Xaml扩展标记&#xff0c; WPF绑定一个控件是使用Binding.ElementName, 绑定非控件对象时使用Source,RelativeSource,DataContex…

【设计模式 04】代理模式

代理模式 代理模式( Proxy)&#xff1a;为其他对象提供一种代理以控制对这个对象的访问。 参考&#xff1a;refactoringguru | proxy 什么是代理模式 有时候如果想要访问某个对象&#xff0c;但又没办法直接访问或不方便直接访问&#xff0c;可以使用代理模式&#xff0c;代理…

css 大于号 标签_CSS设计基础选择器篇

点击上方 Java项目学习 &#xff0c;选择 星标 公众号重磅资讯、干货&#xff0c;第一时间送达前言&#xff1a;如果将CSS样式应用于特定的网页对象上&#xff0c;需要先找到目标元素。在CSS样式中执行这一任务的部分被称为选择器。1 标签选择器优点&#xff1a;为页面中同类型…

crontab 提示 command not found 解决方案

crontab 提示 command not found 解决方案 今天遇见一个问题&#xff0c;crontab的定时任务会报错&#xff1a;java command not found&#xff0c;但是手动执行脚本一直能成功。 猜想是环境变量的问题。 在crontab里添加个打印环境变量的任务&#xff1a; * * * * * echo $PAT…

【设计模式 05】工厂方法模式

工厂方法模式 define an interface or abstract class for creating an object but let the subclasses decide which class to instantiate. 参考&#xff1a; refactoringguru | factory-methodjavatpoint | factory-method-design-pattern博客园| 工厂方法 简单工厂的问题 …