角丸 → 角丸++ ときて、さすがに Objective-角丸は無理があるだろうということで、不本意ながらも#。
と、そんなことはどうでもいいんですが、昨日のやつをさらに改良しました。
角丸自体は Safari 2.0.3 / IE 6.0 / Firefox 1.5.0.1 / Opera 8.5.3 でちゃんと動作することを確認していますが、例によって下のサンプルは Safari 2.0.3 でしか期待通りにレンダリングされません。
test.html
<html> <head> <title>test</title> <script type="text/javascript" src="mynifty.js"></script> <script type="text/javascript"> var Eclipse = new MyNiftyCorner(-1, 'gray', '#ccc', 64, 4, '#000'); var Linear = new MyNiftyCorner(0, '#aff', 'transparent', 20, 1, '#00002a', 2); var Rounder = new MyNiftyCorner(1, 'white', 'gray', 12); var b64 = 'iVBORw0KGgoAAAANSUhEUgAAADwAAABQCAYAAABFyhZTAAAABHNCSVQICAgIfAhk' /* snip */ + '+Bfj/wJAv+2N5Ub+YQAAAABJRU5ErkJggg=='; window.onload = function() { var div0 = document.getElementById('pre'); var div1 = document.getElementById('flt'); var div2 = document.getElementById('abs'); var txt = document.createTextNode(b64.replace(/(.{144})/g, '$1?n')); div0.appendChild(txt); try { var obj1 = document.createElement('object'); obj1.setAttribute('data', 'data:image/png;base64,' + b64); div1.appendChild(obj1); var obj2 = obj1.cloneNode(); obj2.style.width = '240px'; obj2.style.height = '320px'; div2.appendChild(obj2); } catch (e) { window.alert(e.toString()); if (!obj1) { div1.appendChild(document.createTextNode('Error1')); } if (!obj2) { div2.appendChild(document.createTextNode('Error2')); } } Eclipse.roundAndPad(document.body); Rounder.roundAndPad(div0); Linear.roundAndPad(div2); } </script> <style type="text/css"> body { margin:10px; padding:0px; background-color:#ccc; } #pre { position:relative; white-space:pre; margin:0px; background-color:#ffc; font-family:monospace; font-size:8px; line-height:100%; } #abs { position:absolute; bottom:10%; left:10%; z-index:1; font:36px bold; color:red; opacity:0.5; } #flt { float:left; font:36px bold; color:red; } </style> </head> <body> <div id="pre"><div id="abs"></div><div id="flt"></div></div> </body> </html>
mynifty.js
if (!Number.square) { Number.prototype.square = function() { return Math.pow(this, 2); }} if (!Number.cube) { Number.prototype.cube = function() { return Math.pow(this, 3); }} if (!Number.sqrt) { Number.prototype.sqrt = function() { return Math.sqrt(this); }} if (!Number.floor) { Number.prototype.floor = function() { return Math.floor(this); }} if (!Number.ceil) { Number.prototype.ceil = function() { return Math.ceil(this); }} if (!Number.round) { Number.prototype.round = function() { return Math.round(this); }} if (!Math.hypot) { Math.hypot = function(x, y) { return (x.square() + y.square()).sqrt(); }} if (!Math.base) { Math.base = function(z, y) { return (z.square() - y.square()).sqrt(); }} var MyNiftyStyle = '<style type="text/css">' + 'span.NiftyElement {' + 'display:block;' + 'margin:0;' + 'padding:0;' + 'overflow:hidden;' + 'overflow-x:hidden;' + 'overflow-y:hidden;' + '}' + '</style>'; document.write(MyNiftyStyle); function MyNiftyCorner() { // {{{ 初期化 var self = this; var mode = 'round'; if (arguments.length > 0) { mode = arguments[0].toString(); switch (arguments[0]) { case 0: mode = 'linear'; break; case -1: mode = 'flipped'; break; } } this._bgcolor = (arguments.length > 1) ? arguments[1].toString() : '#fff'; this._color = (arguments.length > 2) ? arguments[2].toString() : '#ccc'; this._size = (arguments.length > 3 && parseInt(arguments[3]) > 0) ? parseInt(arguments[3]) : 5; this._step = (arguments.length > 4 && parseInt(arguments[4]) > 0) ? parseInt(arguments[4]) : 1; this._size = Math.max(this._size, this._step); this._bdcolor = (arguments.length > 5) ? arguments[5].toString() : null; this._bdwidth = (arguments.length > 6 && parseInt(arguments[6]) > 0) ? parseInt(arguments[6]) : 1; this._bdwidth = Math.min(Math.floor(this._size / this._step), this._bdwidth); // }}} // {{{ 角丸化メソッド this.round = function() { self.roundTop.apply(this, arguments); self.roundBottom.apply(this, arguments); } this.roundTop = function() { var args = self.parseArguments(arguments); var target = args.shift(); target.insertBefore(self.createTop.apply(this, args), target.firstChild); } this.roundBottom = function() { var args = self.parseArguments(arguments); var target = args.shift(); target.appendChild(self.createBottom.apply(this, args)); } this.roundAndPad = function() { var args = self.parseArguments(arguments); var target = args[0]; var bgcolor = args[1]; var color = args[2]; var size = args[3]; var step = args[4]; var bdcolor = args[5]; var bdwidth = args[6]; if (target.childNodes && target.childNodes.length) { var container = document.createElement('div'); container.style.backgroundColor = bgcolor; container.style.margin = '0'; if (bdcolor) { var bdsize = step * bdwidth; container.style.padding = self.intToPixelsHorizontal(size - bdsize); container.style.borderColor = bdcolor; container.style.borderStyle = 'solid'; container.style.borderWidth = self.intToPixelsHorizontal(bdsize); } else { container.style.padding = self.intToPixelsHorizontal(size); } while (target.childNodes.length) { container.appendChild(target.removeChild(target.firstChild)); } target.appendChild(container); } self.roundTop.apply(this, arguments); self.roundBottom.apply(this, arguments); } // }}} // {{{ 要素作成メソッド this.createCorner = function(color, height) { var corner = document.createElement('span'); corner.className = 'NiftyElement'; corner.style.backgroundColor = color; corner.style.height = self.intToPixels(height); corner.unshiftChild = function(newChild) { return this.insertBefore(newChild, this.firstChild); } return corner; } this.createLine = function(color, height, margin) { var line = document.createElement('span'); line.className = 'NiftyElement'; line.style.backgroundColor = color; line.style.height = self.intToPixels(height); line.style.margin = self.intToPixelsHorizontal(margin); return line; } this.createLineBordered = function(color, height, margin, bdcolor, bdwidth) { var line = document.createElement('span'); line.className = 'NiftyElement'; line.style.backgroundColor = color; line.style.height = self.intToPixels(height); line.style.margin = self.intToPixelsHorizontal(margin); line.style.borderColor = bdcolor; line.style.borderStyle = 'solid'; line.style.borderWidth = self.intToPixelsHorizontal(bdwidth); return line; } this.createTop = function() { if (arguments[4]) { if (arguments[5] > 1) { return self._createTopBordered2.apply(this, arguments); } return self._createTopBordered.apply(this, arguments); } return self._createTopSimple.apply(this, arguments); } this.createBottom = function() { if (arguments[4]) { if (arguments[5] > 1) { return self._createBottomBordered2.apply(this, arguments); } return self._createBottomBordered.apply(this, arguments); } return self._createBottomSimple.apply(this, arguments); } this._createTopSimple = function(bgcolor, color, size, step) { var top = self.createCorner(color, size); var i, line; for (i = 0; i < size; i += step) { line = self.createLine(bgcolor, step, self.calcMargin(size, i, step)); top.unshiftChild(line); } return top; } this._createBottomSimple = function(bgcolor, color, size, step) { var bottom = self.createCorner(color, size); var i, line; for (i = 0; i < size; i += step) { line = self.createLine(bgcolor, step, self.calcMargin(size, i, step)); bottom.appendChild(line); } return bottom; } this._createTopBordered = function(bgcolor, color, size, step, bdcolor) { var top = self.createCorner(color, size); var i, line, margin1, bdsize; for (i = 0; i < size - step; i += step) { margin = self.calcMargin(size, i, step); bdsize = Math.max(step, self.calcMargin(size, i + step, step) - margin); line = self.createLineBordered(bgcolor, step, margin, bdcolor, bdsize); top.unshiftChild(line); } line = self.createLine(bdcolor, step, self.calcMargin(size, i, step)); top.unshiftChild(line); return top; } this._createBottomBordered = function(bgcolor, color, size, step, bdcolor) { var bottom = self.createCorner(color, size); var i, line, margin, bdsize; for (i = 0; i < size - step; i += step) { margin = self.calcMargin(size, i, step); bdsize = Math.max(step, self.calcMargin(size, i + step, step) - margin); line = self.createLineBordered(bgcolor, step, margin, bdcolor, bdsize); bottom.appendChild(line); } line = self.createLine(bdcolor, step, self.calcMargin(size, i, step)); bottom.appendChild(line); return bottom; } this._createTopBordered2 = function(bgcolor, color, size, step, bdcolor, bdwidth) { var top = self.createCorner(color, size); var bdsize = step * bdwidth; var insize = size - bdsize; var i, line, margins; for (i = 0; i < insize; i += step) { margins = self.calcMargin2(size, insize, bdsize, i, step); line = self.createLineBordered(bgcolor, step, margins[0], bdcolor, margins[1]); top.unshiftChild(line); } while (i < size) { line = self.createLine(bdcolor, step, self.calcMargin2(size, insize, bdsize, i, step)[0]); top.unshiftChild(line); i += step; } return top; } this._createBottomBordered2 = function(bgcolor, color, size, step, bdcolor, bdwidth) { var bottom = self.createCorner(color, size); var bdsize = step * bdwidth; var insize = size - bdsize ; var i, line, margins; for (i = 0; i < insize; i += step) { margins = self.calcMargin2(size, insize, bdsize, i, step); line = self.createLineBordered(bgcolor, step, margins[0], bdcolor, margins[1]); bottom.appendChild(line); } while (i < size) { line = self.createLine(bdcolor, step, self.calcMargin2(size, insize, bdsize, i, step)[0]); bottom.appendChild(line); i += step; } return bottom; } // }}} // {{{ ユーティリティメソッド this.parseArguments = function(args) { var params = []; if (args.lengs == 0) { window.alert('argument #1 is required.'); return []; } params[0] = (typeof args[0] == 'string') ? document.getElementById(args[0]) : args[0]; if (!params[0] || !params[0].appendChild) { window.alert('argument #1 must be a DOM Element or an existing Element ID.'); return []; } params[1] = (args.length > 1) ? args[1].toString() : self._bgcolor; params[2] = (args.length > 2) ? args[2].toString() : self._color; params[3] = (args.length > 3 && parseInt(args[3]) > 0) ? parseInt(args[3]) : self._size; params[4] = (args.length > 4 && parseInt(args[4]) > 0) ? parseInt(args[4]) : self._step; params[3] = Math.max(params[3], params[4]); params[5] = (args.length > 5) ? args[5].toString() : self._bdcolor; params[6] = (args.length > 6 && parseInt(args[6]) > 0) ? parseInt(args[6]) : self._bdwidth; params[6] = Math.min(Math.floor(params[3] / params[4]), params[6]); return params; } switch (mode) { case 'line': case 'linear': case 'straight': this.calcMargin = function(size, level, step) { return level; } this.calcMargin2 = function(size, insize, bdsize, level, step) { return [level, bdsize]; } break; case 'flip': case 'flipped': case 'eclipse': this.calcMargin = function(size, level, step) { return Math.floor(Math.base(size, size - level) / step) * step; } this.calcMargin2 = function(size, insize, bdsize, level, step) { var m0 = 0, m1 = 0; if (level >= bdsize) { m0 = self.calcMargin(insize, level - bdsize, step); } if (level < insize) { m1 = Math.max(self.calcMargin(size, level, step), self.calcMargin(insize, level, step)); } return [m0, Math.max(bdsize, m1 - m0)]; } break; case 'round': default: this.calcMargin = function(size, level, step) { return size - Math.floor(Math.base(size, level + step) / step) * step; } this.calcMargin2 = function(size, insize, bdsize, level, step) { var m0 = 0, m1 = 0; m0 = self.calcMargin(size, level, step); if (level < insize) { m1 = Math.max(self.calcMargin(insize, level, step), self.calcMargin(size, level + bdsize, step)); } return [m0, Math.max(bdsize, m1 - m0)]; } } this.intToPixels = function(num) { return parseInt(num).toString() + 'px'; } this.intToPixelsVertical = function(num) { return self.intToPixels(num) + ' 0'; } this.intToPixelsHorizontal = function(num) { return '0 ' + self.intToPixels(num); } // }}} }