commit ccb310c960e15fc00ce1b578ecc8f2b3a8f264b7 Author: richie Date: Fri Nov 16 13:55:00 2018 +0800 时钟示例源码 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ddedc28 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +*.iml +.idea/ +target/ +lib/report/*.jar +.classpath \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..e2b32ff --- /dev/null +++ b/README.md @@ -0,0 +1,29 @@ +# 时钟控件 +功能:表单里的时钟控件,可以动态的展示当前的时间 + +最终动态gif效果图: + + +使用Canvas实现 +![Canvas实现的动态效果图](effect/clock.gif) + +使用CSS3实现 +![Css3实现的动态效果图](effect/clock_css3.gif) + +设计器效果图: + +控件选择界面: +![控件选择界面](effect/designer_effect1.png) + +表单设计界面 +![表单设计界面](effect/designer_effect2.png) + +表单预览效果图 + +Canvas版本 +![表单预览效果图](effect/clock_preview_inform.png) + +CSS3版本 +![表单预览效果图](effect/clock_review_css3.png) + + diff --git a/build.xml b/build.xml new file mode 100644 index 0000000..4067617 --- /dev/null +++ b/build.xml @@ -0,0 +1,130 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/effect/clock.gif b/effect/clock.gif new file mode 100644 index 0000000..32c2dd5 Binary files /dev/null and b/effect/clock.gif differ diff --git a/effect/clock_css3.gif b/effect/clock_css3.gif new file mode 100644 index 0000000..223a8c2 Binary files /dev/null and b/effect/clock_css3.gif differ diff --git a/effect/clock_preview_inform.png b/effect/clock_preview_inform.png new file mode 100644 index 0000000..7a8cfe8 Binary files /dev/null and b/effect/clock_preview_inform.png differ diff --git a/effect/clock_review_css3.png b/effect/clock_review_css3.png new file mode 100644 index 0000000..43d8087 Binary files /dev/null and b/effect/clock_review_css3.png differ diff --git a/effect/designer_effect1.png b/effect/designer_effect1.png new file mode 100644 index 0000000..2b8c7da Binary files /dev/null and b/effect/designer_effect1.png differ diff --git a/effect/designer_effect2.png b/effect/designer_effect2.png new file mode 100644 index 0000000..214181a Binary files /dev/null and b/effect/designer_effect2.png differ diff --git a/lib/report/.gitkeep b/lib/report/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/plugin.xml b/plugin.xml new file mode 100644 index 0000000..fe1dc5c --- /dev/null +++ b/plugin.xml @@ -0,0 +1,22 @@ + + com.fr.plugin.widget.clock + com.fr.plugin.widget + + yes + 1.1 + 10.0 + 2018-10-09 + author + + + ]]> + + + + + + + + + \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..5503215 --- /dev/null +++ b/pom.xml @@ -0,0 +1,29 @@ + + + 4.0.0 + + + com.fr.plugin + starter + 10.0 + + + jar + demo-show-clock + + + ${project.basedir}/../webroot/WEB-INF/plugins/plugin-com.fr.plugin.widget.clock-1.0/classes + + + org.apache.maven.plugins + maven-compiler-plugin + + 6 + 6 + + + + + \ No newline at end of file diff --git a/src/main/java/com/fr/plugin/widget/clock/ClockBridge.java b/src/main/java/com/fr/plugin/widget/clock/ClockBridge.java new file mode 100644 index 0000000..898f2f0 --- /dev/null +++ b/src/main/java/com/fr/plugin/widget/clock/ClockBridge.java @@ -0,0 +1,40 @@ +package com.fr.plugin.widget.clock; + +import com.fr.design.fun.impl.AbstractFormWidgetOptionProvider; +import com.fr.form.ui.Widget; +import com.fr.locale.InterProviderFactory; +import com.fr.plugin.widget.clock.fun.Clock; +import com.fr.plugin.widget.clock.ui.XClock; + +/** + * @author richie + * @date 2015-03-23 + * @since 8.0 + */ +public class ClockBridge extends AbstractFormWidgetOptionProvider { + + @Override + public Class classForWidget() { + return Clock.class; + } + + @Override + public Class appearanceForWidget() { + return XClock.class; + } + + @Override + public String iconPathForWidget() { + return "/com/fr/plugin/widget/clock/images/clock.png"; + } + + @Override + public String nameForWidget() { + return InterProviderFactory.getProvider().getLocText("Plugin-Clock_Name"); + } + + @Override + public boolean isContainer() { + return false; + } +} \ No newline at end of file diff --git a/src/main/java/com/fr/plugin/widget/clock/ClockJavaScriptFileBridge.java b/src/main/java/com/fr/plugin/widget/clock/ClockJavaScriptFileBridge.java new file mode 100644 index 0000000..efd8965 --- /dev/null +++ b/src/main/java/com/fr/plugin/widget/clock/ClockJavaScriptFileBridge.java @@ -0,0 +1,19 @@ +package com.fr.plugin.widget.clock; + +import com.fr.stable.fun.impl.AbstractJavaScriptFileHandler; + +/** + * @author richie + * @date 2015-03-23 + * @since 8.0 + * 如果要使用canvas实现的时钟,就使用widget.clock.js这个文件 + * 如果要使用css3实现的时钟,就使用widget.otherclock.js这个文件 + */ +public class ClockJavaScriptFileBridge extends AbstractJavaScriptFileHandler { + @Override + public String[] pathsForFiles() { + return new String[]{ + "/com/fr/plugin/widget/clock/widget.otherclock.js" + }; + } +} \ No newline at end of file diff --git a/src/main/java/com/fr/plugin/widget/clock/fun/Clock.java b/src/main/java/com/fr/plugin/widget/clock/fun/Clock.java new file mode 100644 index 0000000..ba3c7a3 --- /dev/null +++ b/src/main/java/com/fr/plugin/widget/clock/fun/Clock.java @@ -0,0 +1,40 @@ +package com.fr.plugin.widget.clock.fun; + +import com.fr.form.ui.Widget; +import com.fr.intelli.record.Focus; +import com.fr.intelli.record.Original; +import com.fr.json.JSONException; +import com.fr.json.JSONObject; +import com.fr.record.analyzer.EnableMetrics; +import com.fr.script.Calculator; +import com.fr.stable.core.NodeVisitor; +import com.fr.stable.web.Repository; + +/** + * @author richie + * @date 2015-03-23 + * @since 8.0 + */ +@EnableMetrics +public class Clock extends Widget { + @Override + public String getXType() { + return "clock"; + } + + @Override + @Focus(id="ClockConstants", text = "Plugin-Clock_Name", source = Original.PLUGIN) + public JSONObject createJSONConfig(Repository repository, Calculator calculator, NodeVisitor nodeVisitor) throws JSONException { + return super.createJSONConfig(repository, calculator, nodeVisitor); + } + + @Override + public boolean isEditor() { + return false; + } + + @Override + public String[] supportedEvents() { + return new String[0]; + } +} \ No newline at end of file diff --git a/src/main/java/com/fr/plugin/widget/clock/fun/ClockConstants.java b/src/main/java/com/fr/plugin/widget/clock/fun/ClockConstants.java new file mode 100644 index 0000000..4a7ed24 --- /dev/null +++ b/src/main/java/com/fr/plugin/widget/clock/fun/ClockConstants.java @@ -0,0 +1,6 @@ +package com.fr.plugin.widget.clock.fun; + +public class ClockConstants { + + public static final String PLUGIN_ID = "com.fr.plugin.widget.clock"; +} diff --git a/src/main/java/com/fr/plugin/widget/clock/ui/XClock.java b/src/main/java/com/fr/plugin/widget/clock/ui/XClock.java new file mode 100644 index 0000000..4dd0a17 --- /dev/null +++ b/src/main/java/com/fr/plugin/widget/clock/ui/XClock.java @@ -0,0 +1,32 @@ +package com.fr.plugin.widget.clock.ui; + +import com.fr.design.designer.creator.XWidgetCreator; +import com.fr.general.IOUtils; +import com.fr.plugin.widget.clock.fun.Clock; + +import javax.swing.*; +import java.awt.*; + +/** + * @author richie + * @date 2015-03-23 + * @since 8.0 + */ +public class XClock extends XWidgetCreator { + + public XClock(Clock widget, Dimension initSize) { + super(widget, initSize); + } + + @Override + protected JComponent initEditor() { + if (editor == null) { + editor = new JLabel(IOUtils.readIcon(getIconPath())); + } + return editor; + } + + public String getIconPath() { + return "/com/fr/plugin/widget/clock/images/clock.png"; + } +} \ No newline at end of file diff --git a/src/main/resources/com/fr/plugin/widget/clock/images/clock.png b/src/main/resources/com/fr/plugin/widget/clock/images/clock.png new file mode 100644 index 0000000..3689ba2 Binary files /dev/null and b/src/main/resources/com/fr/plugin/widget/clock/images/clock.png differ diff --git a/src/main/resources/com/fr/plugin/widget/clock/locale/clock.properties b/src/main/resources/com/fr/plugin/widget/clock/locale/clock.properties new file mode 100644 index 0000000..43d521d --- /dev/null +++ b/src/main/resources/com/fr/plugin/widget/clock/locale/clock.properties @@ -0,0 +1 @@ +Plugin-Clock_Name=Clock \ No newline at end of file diff --git a/src/main/resources/com/fr/plugin/widget/clock/locale/clock_zh_CN.properties b/src/main/resources/com/fr/plugin/widget/clock/locale/clock_zh_CN.properties new file mode 100644 index 0000000..7953598 --- /dev/null +++ b/src/main/resources/com/fr/plugin/widget/clock/locale/clock_zh_CN.properties @@ -0,0 +1 @@ +Plugin-Clock_Name=\u65F6\u949F \ No newline at end of file diff --git a/src/main/resources/com/fr/plugin/widget/clock/widget.clock.js b/src/main/resources/com/fr/plugin/widget/clock/widget.clock.js new file mode 100644 index 0000000..88a7778 --- /dev/null +++ b/src/main/resources/com/fr/plugin/widget/clock/widget.clock.js @@ -0,0 +1,125 @@ +(function () { + /** + * @class FR.Clock + * @extends FR.Widget + * 这个时钟使用canvas画的 + */ + FR.Clock = FR.extend(FR.Widget, { + _defaultConfig: function () { + return $.extend(FR.Clock.superclass._defaultConfig.apply(), { + baseCls: 'fr-clock' + }); + }, + + _init: function () { + FR.Clock.superclass._init.apply(this, arguments); + var o = this.options; + var wh = Math.min(o.width, o.height); + this.$canvas = $("").attr({ + width: wh, + height: wh + }).css({ + position : 'absolute', + top : wh == o.width ? (o.height - wh) / 2 : 0, + left : wh == o.height ? (o.width - wh) / 2 : 0 + }).appendTo(this.element); + this.draw(this.$canvas[0]); + }, + + draw: function (canvas) { + var ctx = canvas.getContext("2d"); + this.ctx = ctx; + var radius = canvas.height / 2; + ctx.translate(radius, radius); + radius = radius * 0.90 + setInterval(drawClock, 1000); + + function drawClock() { + drawFace(ctx, radius); + drawNumbers(ctx, radius); + drawTime(ctx, radius); + } + + function drawFace(ctx, radius) { + var grad; + ctx.beginPath(); + ctx.arc(0, 0, radius, 0, 2 * Math.PI); + ctx.fillStyle = 'white'; + ctx.fill(); + grad = ctx.createRadialGradient(0, 0, radius * 0.95, 0, 0, radius * 1.05); + grad.addColorStop(0, '#333'); + grad.addColorStop(0.5, 'white'); + grad.addColorStop(1, '#333'); + ctx.strokeStyle = grad; + ctx.lineWidth = radius * 0.1; + ctx.stroke(); + ctx.beginPath(); + ctx.arc(0, 0, radius * 0.1, 0, 2 * Math.PI); + ctx.fillStyle = '#333'; + ctx.fill(); + } + + function drawNumbers(ctx, radius) { + var ang; + var num; + ctx.font = radius * 0.15 + "px arial"; + ctx.textBaseline = "middle"; + ctx.textAlign = "center"; + for (num = 1; num < 13; num++) { + ang = num * Math.PI / 6; + ctx.rotate(ang); + ctx.translate(0, -radius * 0.85); + ctx.rotate(-ang); + ctx.fillText(num.toString(), 0, 0); + ctx.rotate(ang); + ctx.translate(0, radius * 0.85); + ctx.rotate(-ang); + } + } + + function drawTime(ctx, radius) { + var now = new Date(); + var hour = now.getHours(); + var minute = now.getMinutes(); + var second = now.getSeconds(); + //hour + hour = hour % 12; + hour = (hour * Math.PI / 6) + + (minute * Math.PI / (6 * 60)) + + (second * Math.PI / (360 * 60)); + drawHand(ctx, hour, radius * 0.5, radius * 0.07); + //minute + minute = (minute * Math.PI / 30) + (second * Math.PI / (30 * 60)); + drawHand(ctx, minute, radius * 0.8, radius * 0.07); + // second + second = (second * Math.PI / 30); + drawHand(ctx, second, radius * 0.9, radius * 0.02); + } + + function drawHand(ctx, pos, length, width) { + ctx.beginPath(); + ctx.lineWidth = width; + ctx.lineCap = "round"; + ctx.moveTo(0, 0); + ctx.rotate(pos); + ctx.lineTo(0, -length); + ctx.stroke(); + ctx.rotate(-pos); + } + }, + + doResize: function (give) { + //var o = this.options, canvas = this.$canvas[0]; + FR.Clock.superclass.doResize.apply(this, arguments); + //var wh = Math.min(o.width, o.height); + //canvas.width = wh; + //canvas.height = wh; + //canvas.style.top = wh == o.width ? (o.height - wh) / 2 : 0 + "px"; + //canvas.style.left = wh == o.height ? (o.width - wh) / 2 : 0 + "px"; + //this.ctx.clearRect(0, 0, 2000, 2000); + //this.draw(this.$canvas[0]); + } + + }); + $.shortcut("clock", FR.Clock); +})(jQuery); \ No newline at end of file diff --git a/src/main/resources/com/fr/plugin/widget/clock/widget.otherclock.js b/src/main/resources/com/fr/plugin/widget/clock/widget.otherclock.js new file mode 100644 index 0000000..f2499e8 --- /dev/null +++ b/src/main/resources/com/fr/plugin/widget/clock/widget.otherclock.js @@ -0,0 +1,120 @@ +(function () { + $.extend(FR, { + rotateTo : function(d) { + return '-webkit-transform:rotate(' + d + 'deg);-moz-transform:rotate(' + d + 'deg);-o-transform:rotate(' + d + 'deg);-ms-transform:rotate(' + d + 'deg);' + } + }); + /** + * @class FR.OtherClock + * @extends FR.Widget + * 这个时钟是用CSS3实现的 + */ + FR.OtherClock = FR.extend(FR.Widget, { + _defaultConfig: function () { + return $.extend(FR.OtherClock.superclass._defaultConfig.apply(), { + baseCls: 'fr-clock' + }); + }, + + _init: function () { + FR.OtherClock.superclass._init.apply(this, arguments); + this._buildAndRun(); + }, + + _createClockHtml: function (o) { + var p = 'position:absolute;left:50%;top:50%;', hw = o.w * 0.04, hh = o.w * 0.52, mw = o.w * 0.04, mh = o.w * 0.64, sw = o.w * 0.02, sh = o.w * 0.98, a = ""; + + function rotateTo(d) { + return '-webkit-transform:rotate(' + d + 'deg);-moz-transform:rotate(' + d + 'deg);-o-transform:rotate(' + d + 'deg);-ms-transform:rotate(' + d + 'deg);' + } + + function setCover(s, z, c) { + return '
' + } + + function setHands(hand, width, height, color, index) { + return '

' + } + + for (var n = 0; n < 30; n++) { + var nd = n * 6; + a += '

' + } + for (var j = 0; j < 6; j++) { + var jd = j * 30; + a += '

' + } + for (var i = 1; i < 13; i++) { + var id = i * 30; + a += '

' + i + '

' + } + var pc = '
' + setCover(0.96, 1, o.bc) + setCover(0.92, 3, o.bc) + setCover(0.08, 8, '#555') + setCover(0.02, 9, '#eee') + setHands('clock-h', hw, hh, o.hc, 5) + setHands('clock-m', mw, mh, o.mc, 6) + setHands('clock-s', sw, sh, o.sc, 7); + pc += a; + pc += '
'; + return pc; + }, + + run : function() { + var self = this; + var t = new Date(), h = t.getHours(), m = t.getMinutes(), s = t.getSeconds(); + if (h > 12) { + h -= 12 + } + $('.clock-s', this.element).each(function(){ + this.style.cssText += FR.rotateTo(6 * s); + }); + $('.clock-m', this.element).each(function(){ + this.style.cssText += FR.rotateTo(6 * m + 0.1 * s); + }); + $('.clock-h', this.element).each(function(){ + this.style.cssText += FR.rotateTo(30 * h + 0.5 * m + s / 120); + }); + if (this.stopped !== true) { + setTimeout(function () { + self.run(); + }, 30) + } + }, + + /** + * 对外开放的API,在停止时钟转动后,重新启动 + */ + start : function() { + this.stopped = false; + this.run(); + }, + + /** + * 停止时钟转动 + */ + stop : function() { + this.stopped = true; + }, + + _buildAndRun : function() { + var o = this.options; + var w = Math.min(o.width, o.height); + this.element[0].innerHTML = ''; + this.element[0].innerHTML = this._createClockHtml({ + id : o.widgetName, + w: w - w * 0.04 * 2, + top : w == o.width ? (o.height - w) / 2 : 0, + left : w == o.height ? (o.width - w) / 2 : 0, + c: "#6c0", // 钟框颜色 + bc: "#fff", // 钟面颜色 + hc: "#333", // 时针颜色 + mc: "#DDB11A", // 分针颜色 + sc: "#DC0D07" // 秒针颜色 + }); + var self = this; + setTimeout(self.run.createDelegate(self), 200); + }, + + doResize: function (give) { + FR.OtherClock.superclass.doResize.apply(this, arguments); + this._buildAndRun(); + } + + }); + $.shortcut("clock", FR.OtherClock); +})(jQuery); \ No newline at end of file