imported>=海豚= |
imported>Irukaza |
第1行: |
第1行: |
| <style> | | <noinclude>Only for {{tl|萌百 页面 嵌 入}}</noinclude> |
| * {
| | <includeonly> |
| margin: 0;
| |
| }
| |
| .timeline {
| |
| height: 100%;
| |
| position: relative;
| |
| }
| |
| .timeline canvas {
| |
| position: absolute;
| |
| width: 100%;
| |
| height: 100%;
| |
| left: 0;
| |
| top: 46px;
| |
| }
| |
| .timeline figcaption {
| |
| font-weight: 400;
| |
| font-size: 24px;
| |
| text-transform: uppercase;
| |
| -webkit-text-stroke: .25px;
| |
| }
| |
| .timeline h2 {
| |
| font-weight: 400;
| |
| font-size: 30px;
| |
| padding-bottom: 20px;
| |
| color: #b2cde9!important;
| |
| text-transform: uppercase;
| |
| line-height: 1.2 !important;
| |
| }
| |
| .timeline h6 {
| |
| color: #0090F5!important;
| |
| font-size: 17px;
| |
| font-weight: 400;
| |
| }
| |
| .timeline p,
| |
| .timeline ol {
| |
| font-weight: 400;
| |
| padding: 3px 0 20px 0;
| |
| color: #575757!important;
| |
| text-align: justify;
| |
| width: 70%;
| |
| }
| |
| .timeline ol {
| |
| list-style: disc;
| |
| margin-top: -20px;
| |
| padding-left: 40px;
| |
| }
| |
| .timeline figure {
| |
| float: right;
| |
| width: 100%;
| |
| }
| |
| .timeline article {
| |
| position: relative;
| |
| width: 38%;
| |
| overflow: hidden;
| |
| }
| |
| .timeline article:first-of-type {
| |
| float: left;
| |
| text-align: right;
| |
| }
| |
| .timeline article:first-of-type p,
| |
| .timeline article:first-of-type figure {
| |
| float: right;
| |
| }
| |
| .timeline article:last-of-type {
| |
| float: right;
| |
| }
| |
| .timeline article:last-of-type h2 {
| |
| color: #c6e0aa!important;
| |
| }
| |
| .timeline article:last-of-type h6,
| |
| .timeline article:last-of-type a {
| |
| color: #40aa00!important;
| |
| }
| |
| .timeline article:last-of-type a:hover {
| |
| color: #95D40D!important;
| |
| }
| |
| </style>
| |
| </head>
| |
| <body>
| |
| <section id="timeline">
| |
| | |
| <div class="timeline">
| |
| <canvas id="cvs3"></canvas>
| |
| <article>
| |
| <h2>新增功能</h2>
| |
| <figure>
| |
| <figcaption>全站系统版本更新</figcaption>
| |
| <h6>2021.6.23</h6>
| |
| <p>
| |
| 升级至2021年6月23日维基媒体发布的MW1.31.15(c755afe) 补丁版本,此次更新跨越了7个小版本。
| |
| </p>
| |
| </figure>
| |
| <figure>
| |
| <figcaption>看板娘系统重构</figcaption>
| |
| <h6>2021.6.26-27</h6>
| |
| <p>
| |
| 去除冗余代码;新增5个看板娘;加入换装功能(为 pio酱 提供了86套皮肤 / 为 Tia酱 提供了62套皮肤 / 为 22、33 提供了21套皮肤 / 为 22、33 提供了21套皮肤 / 为 海王星 提供了19套皮肤)。
| |
| </p>
| |
| </figure>
| |
| <figure>
| |
| <figcaption>支持繁简转换</figcaption>
| |
| <h6>2021.7.12-14</h6>
| |
| <p>
| |
| 增添繁简转换插件,在左上角显示按钮,可在所有 页面 使用,支持繁体源代码编辑和繁体字搜索。
| |
| </p>
| |
| </figure>
| |
| <figure>
| |
| <figcaption>编辑记录页改版</figcaption>
| |
| <h6>2021.7.15-16</h6>
| |
| <p>
| |
| 添加图标;引 入 显示维护组用户的用户组的小工具;并更新最近更改图例。
| |
| </p>
| |
| </figure>
| |
| <figure>
| |
| <figcaption>左侧显示浮动目录</figcaption>
| |
| <h6>2021.8.10-12</h6>
| |
| <p>
| |
| 当条目中的标题超过三个时,条目左侧会出现目录,侧边栏划上去时可以看见,点击可跳转到指定标题。
| |
| </p>
| |
| </figure>
| |
| <figure>
| |
| <figcaption>用户贡献页改版</figcaption>
| |
| <h6>2021.8.13</h6>
| |
| <p>
| |
| 改变顶部用户信息控制栏;维护组用户可分名字空间查看其他用户的编辑数量。
| |
| </p>
| |
| </figure>
| |
| </article>
| |
| <article>
| |
| <h2>修复漏洞</h2>
| |
| <figure>
| |
| <figcaption>Mobile Friendly</figcaption>
| |
| <h6>with touch screen</h6>
| |
| <p>
| |
| Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam et ipsum pulvinar, blandit neque in, ornare libero.
| |
| </p>
| |
| </figure>
| |
| <figure>
| |
| <figcaption>Mobile Friendly</figcaption>
| |
| <h6>with touch screen</h6>
| |
| <p>
| |
| Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam et ipsum pulvinar, blandit neque in, ornare libero.
| |
| </p>
| |
| </figure>
| |
| <figure>
| |
| <figcaption>Web Design</figcaption>
| |
| <h6>using Html CSS JS</h6>
| |
| <p>
| |
| Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam et ipsum pulvinar, blandit neque in, orn
| |
| </p>
| |
| </figure>
| |
| <figure>
| |
| <figcaption>Retina Ready Display</figcaption>
| |
| <h6>Supported all devices</h6>
| |
| <p>
| |
| Lorem ipsum dolor sit amet, consectetur adipisicing elit. Architecto, molestiae, perferendis. Iusto nam libero doloribus veritatis ma
| |
| </p>
| |
| </figure>
| |
| <figure>
| |
| <figcaption>Retina Ready Display</figcaption>
| |
| <h6>Supported all devices</h6>
| |
| <p>
| |
| Lorem ipsum dolor sit amet, consectetur adipisicing elit. Architecto, molestiae, perferendis. Iusto nam libero doloribus v
| |
| </p>
| |
| </figure>
| |
| </article>
| |
| <br style="clear:both" />
| |
| </div>
| |
| | |
| </section>
| |
| <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
| |
| <script> | | <script> |
| function Timeline(cvs) {
| | const jsonp = (() => { |
| | | let incrementCallbackKey = 0 |
| var self = this,
| | |
| paused = true,
| | return function jsonp(config) { |
| rafid = 0,
| | return new Promise((resolve, reject) => { |
| mouse = { x: 0, y: 0 },
| | const scriptTag = document.createElement('script') |
| canvas = cvs,
| | const requestUrl = config.url + '?' + new URLSearchParams({ |
| ctx = null;
| | ...config.params, |
| | | callback: '___jsonpCallback' + ++incrementCallbackKey, |
| self.lines = [];
| | }).toString() |
| | |
| self.isOK = false;
| |
| self.options = {
| |
| speed: 0.1,
| |
| density: 8,
| |
| radius: 600,
| |
| };
| |
| self.targets = [
| |
| [20, 26, 58, 64, 114, 116],
| |
| [26, 29, 30, 90 , 95, 110]
| |
| ];
| |
| self.dotColors = [
| |
| ['#13669b', 'rgba(19, 102, 155, 0.3)', 'rgba(19, 102, 155, 0.08)'],
| |
| ['#7dd317', 'rgba(113, 222, 15, 0.3)', 'rgba(91, 164, 22, 0.12)'],
| |
| ];
| |
| | |
| self.isPaused = function () {
| |
| return paused;
| |
| };
| |
| | |
| function InitDots() {
| |
| var tl = $('.timeline');
| |
| var top = tl.find('h2').outerHeight();
| |
| | |
| self.lines[0].dots = []; | |
| var y = top; | |
| tl.find('article:first figure').each(function () {
| |
| | |
| self.lines[0].dots.push([$(this).outerWidth() + 20, y + 20]);
| |
| | |
| y += $(this).outerHeight();
| |
| });
| |
|
| |
|
| self.lines[1].dots = [];
| | scriptTag.src = requestUrl |
| var y = top;
| | window['___jsonpCallback' + incrementCallbackKey] = resolve |
| tl.find('article:last figure').each(function () {
| | scriptTag.onload = () => scriptTag.remove() |
| | scriptTag.onerror = () => reject(new Error('jsonp request error')) |
| | document.body.appendChild(scriptTag) |
| | setTimeout(() => reject(new Error('jsonp request timeout')), 1_000) |
| | }) |
| | } |
| | })() |
|
| |
|
| self.lines[1].dots.push([canvas.width - $(this).outerWidth() - 20, y + 20]);
| | jsonp({ |
| | | url: 'https://zh.moegirl.org/api.php', |
| y += $(this).outerHeight();
| | params: { |
| });
| | action: 'parse', |
| | format: 'json', |
| | page:document.body.querySelector('#moe').dataset.pagename |
| | } |
| | }) |
| | .then(data => { |
| | if (data.error) { |
| | throw new Error(data.error.info) |
| | } else { |
| | document.body.querySelector('#moe').innerHTML = data.parse.text['*'] |
| } | | } |
| | | }) |
| function OnResize() {
| | if(window.name == ""){ |
| canvas.width = canvas.offsetWidth;
| | window.name = "isReload"; |
| canvas.height = canvas.offsetHeight;
| | location.reload(); |
| | | } |
| var wasPaused = paused;
| | else if(window.name == "isReload"){ |
| self.toggle(false);
| |
| // Init lines
| |
| self.lines[0].reset(canvas.offsetWidth / 2 - 15);
| |
| self.lines[1].reset(canvas.offsetWidth / 2 + 15);
| |
| | |
| InitDots();
| |
| | |
| self.toggle(!wasPaused);
| |
| }
| |
| | |
| function init() {
| |
| var result = false;
| |
| try {
| |
| result = !!(canvas.getContext && (ctx = canvas.getContext('2d')));
| |
| | |
| self.lines[0] = new Line(0, canvas.offsetHeight - 100, '#4789a3', self.options, mouse);
| |
| self.lines[1] = new Line(0, canvas.offsetHeight - 100, '#a0d59c', self.options, mouse);
| |
| | |
| } catch (e) {
| |
| return false;
| |
| }
| |
| | |
| $(canvas).mousemove(function (e) {
| |
| | |
| if (e.offsetX) {
| |
| mouse.x = e.offsetX;
| |
| mouse.y = e.offsetY;
| |
| }
| |
| else if (e.layerX) {
| |
| mouse.x = e.layerX;
| |
| mouse.y = e.layerY;
| |
| }
| |
| else {
| |
| mouse.x = e.pageX - $(canvas).offset().left;
| |
| mouse.y = e.pageY - $(canvas).offset().top;
| |
| }
| |
| });
| |
| | |
| $(window).resize(OnResize);
| |
| | |
| OnResize();
| |
| | |
| return result;
| |
| }
| |
| | |
| function Line(y, height, color, options, mouse) {
| |
| var self = this;
| |
| | |
| self.color = color;
| |
| self.options = options;
| |
| self.mouse = mouse;
| |
| self.height = height;
| |
| self.dots = [];
| |
| self.y = y;
| |
| | |
| self.points = [];
| |
| | |
| self.reset = function (x, f) {
| |
| self.points = [];
| |
| for (var y = self.y; y < self.height; y += self.options.density)
| |
| self.points.push(new Point(x, y, self.color));
| |
| }
| |
| | |
| self.update = function () {
| |
| for (var i = 0; i < self.points.length; i++)
| |
| self.points[i].update(self.mouse, self.options);
| |
| }
| |
| | |
| function Point(x, y) {
| |
| this.y = y;
| |
| this.x = x;
| |
| this.base = { x: x, y: y };
| |
| | |
| this.update = function (mouse, options) {
| |
| var dx = this.x - mouse.x,
| |
| dy = this.y - mouse.y,
| |
| alpha = Math.atan2(dx, dy),
| |
| alpha = (alpha > 0 ? alpha : 2 * Math.PI + alpha),
| |
| d = options.radius / Math.sqrt(dx * dx + dy * dy);
| |
| | |
| this.y += Math.cos(alpha) * d + (this.base.y - this.y) * options.speed;
| |
| this.x += Math.sin(alpha) * d + (this.base.x - this.x) * options.speed;
| |
| }
| |
| }
| |
| }
| |
| | |
| function drawCircle(p, r, color) {
| |
| ctx.fillStyle = color;
| |
| ctx.beginPath();
| |
| ctx.arc(p.x, p.y, r, 0, 2 * Math.PI, true);
| |
| ctx.closePath();
| |
| ctx.fill();
| |
| }
| |
| | |
| function drawLine(p1, p2) {
| |
| ctx.beginPath();
| |
| ctx.moveTo(p1.x, p1.y);
| |
| ctx.lineTo(p2.x, p2.y);
| |
| ctx.stroke();
| |
| ctx.closePath();
| |
| }
| |
| | |
| function redraw() {
| |
| ctx.clearRect(0, 0, canvas.width, canvas.height);
| |
| | |
| for (var i = 0; i < 2; i++) {
| |
| var points = self.lines[i].points;
| |
| | |
| ctx.beginPath();
| |
| ctx.lineWidth = 2;
| |
| ctx.strokeStyle = self.lines[i].color;
| |
| ctx.moveTo(points[15].x, points[15].y);
| |
| | |
| for (var j = 15; j < points.length - 2; j++) {
| |
| var point = points[j];
| |
| | |
| var xc = (points[j + 1].x + point.x) / 2;
| |
| var yc = (points[j + 1].y + point.y) / 2;
| |
| | |
| | |
| ctx.quadraticCurveTo(point.x, point.y, xc, yc);
| |
| }
| |
| ctx.stroke();
| |
| ctx.closePath();
| |
| | |
| | |
| // Dots
| |
| ctx.lineWidth = 1.2;
| |
| ctx.strokeStyle = self.dotColors[i][2];
| |
| for (var j = 0; j < self.lines[i].dots.length; j++) {
| |
| var dot = self.lines[i].dots[j],
| |
| id = self.targets[i][j];
| |
| dot2 = [
| |
| (self.lines[i].points[id].x + self.lines[i].points[id + 1].x) / 2,
| |
| (self.lines[i].points[id].y + self.lines[i].points[id + 1].y) / 2,
| |
| ];
| |
| | |
| var p1 = { x: dot[0], y: dot[1] };
| |
| var p2 = { x: dot2[0], y: dot2[1] };
| |
| | |
| | |
| drawLine(p1, p2);
| |
| drawCircle(p1, 4, self.dotColors[i][0]);
| |
| | |
| drawCircle(p2, 11, self.dotColors[i][1]);
| |
| drawCircle(p2, 5.5, self.dotColors[i][0]);
| |
| }
| |
| }
| |
| }
| |
| | |
| function animate() {
| |
| rafid = requestAnimationFrame(animate);
| |
| | |
| self.lines[0].update();
| |
| self.lines[1].update();
| |
| | |
| redraw();
| |
| }
| |
| | |
| self.toggle = function (run) {
| |
| if (!self.isOK) return false;
| |
| | |
| if (run === undefined)
| |
| self.toggle(!paused);
| |
| | |
| else if (!!run && paused) {
| |
| paused = false;
| |
| animate();
| |
| }
| |
| else if (!!!run) {
| |
| paused = true;
| |
| cancelAnimationFrame(rafid);
| |
| }
| |
| return true;
| |
| }
| |
| | |
| | |
| self.isOK = init();
| |
| } | | } |
| new Timeline($('#cvs3').get(0)).toggle(true);
| |
| </script> | | </script> |
| | </includeonly> |