
性懲りも無く更新。たぶんこれで最後です。
- 面取りの幅を約1.41(2の平方根)倍にし、自然に見えるようにした。
- デフォルト値で作成したオブジェクトをキャッシュし、複製することで繰り返し使ったときのパフォーマンスを向上。
ちなみにこれまでのサンプルで Safari と IE 以外ではオブジェクトの複製でエラーが出ていた理由は
DOMElement.cloneNode(true);
の "true" を忘れていたからでした。今回のでは直しています。
test.html
<html>
<head>
<title>test</title>
<script type="text/javascript" src="mynifty2.js"></script>
<script type="text/javascript">
var Beveler = new MyNiftyCorner(0, '#fff', '#8af', 12, 1, '#000', 3);
var Rounder = new MyNiftyCorner(1, '#8af', '#fff', 10);
var b64
= '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';
window.onload = function() {
var txt = document.createTextNode(b64.replace(/(.{72})/g, '$1?n')); // "?n" を バックスラッシュ+n に直してください
var obj1 = document.createElement('object');
obj1.setAttribute('data', 'data:image/png;base64,' + b64);
var obj2 = obj1.cloneNode(true);
obj2.style.width = '276px';
obj2.style.height = '72px';
document.getElementById('pre').appendChild(txt);
document.getElementById('flt').appendChild(obj1);
document.getElementById('abs').appendChild(obj2);
Beveler.roundAndPad(document.body);
Rounder.roundAndPad('flt');
Rounder.roundAndPad('abs');
}
</script>
<style type="text/css">
body { margin:10px; padding:0px; background-color:#8af; }
#pre { position:relative; white-space:pre; margin:0px; background-color:#fff;
font-family:monospace; font-size:12px; 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>
mynifty2.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._default = [this._bgcolor, this._color, this._size, this._step, this._bdcolor, this._bdwidth];
this._defaultId = this._default.join();
this._defaultTop = null;
this._defaultBottom = null;
// }}}
// {{{ 角丸化メソッド
this.round = function()
{
var params = self.parseArguments(arguments);
var target = params.shift();
target.insertBefore(self._createTop(params), target.firstChild);
target.appendChild(self._createBottom(params));
}
this.roundTop = function()
{
var params = self.parseArguments(arguments);
var target = params.shift();
target.insertBefore(self._createTop(params), target.firstChild);
}
this.roundBottom = function()
{
var params = self.parseArguments(arguments);
var target = params.shift();
target.appendChild(self._createBottom(params));
}
this.roundAndPad = function()
{
var params = self.parseArguments(arguments);
var target = params.shift();
var bgcolor = params[0];
var color = params[1];
var size = params[2];
var step = params[3];
var bdcolor = params[4];
var bdwidth = params[5];
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);
}
target.insertBefore(self._createTop(params), target.firstChild);
target.appendChild(self._createBottom(params));
}
// }}}
// {{{ 要素作成メソッド
this._createTop = function(p)
{
if (self._defaultTop && p.join() == self._defaultId) {
return self._defaultTop.cloneNode(true);
}
var corner = self._createCorner(p[1], p[2]);
corner.appendChild = function(newChild)
{
return this.insertBefore(newChild, this.firstChild);
}
if (p[4] == null) {
self._appendLines(corner, p[0], p[2], p[3]);
} else if (p[5] <= 1) {
self._appendLinesBordered(corner, p[0], p[2], p[3], p[4]);
} else {
self._appendLinesBordered2(corner, p[0], p[2], p[3], p[4], p[5]);
}
return corner;
}
this._createBottom = function(p)
{
if (self._defaultBottom && p.join() == self._defaultId) {
return self._defaultBottom.cloneNode(true);
}
var corner = self._createCorner(p[1], p[2]);
if (p[4] == null) {
self._appendLines(corner, p[0], p[2], p[3]);
} else if (p[5] <= 1) {
self._appendLinesBordered(corner, p[0], p[2], p[3], p[4]);
} else {
self._appendLinesBordered2(corner, p[0], p[2], p[3], p[4], p[5]);
}
return corner;
}
this._createCorner = function(bgcolor, height)
{
var corner = document.createElement('span');
corner.className = 'NiftyElement';
corner.style.backgroundColor = bgcolor;
corner.style.height = self.intToPixels(height);
return corner;
}
this._createLine = function(bgcolor, height, margin)
{
var line = document.createElement('span');
line.className = 'NiftyElement';
line.style.backgroundColor = bgcolor;
line.style.height = self.intToPixels(height);
line.style.margin = self.intToPixelsHorizontal(margin);
return line;
}
this._createLineBordered = function(bgcolor, height, margin, bdcolor, bdwidth)
{
var line = document.createElement('span');
line.className = 'NiftyElement';
line.style.backgroundColor = bgcolor;
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._appendLines = function(corner, bgcolor, size, step)
{
var i, line;
for (i = 0; i < size; i += step) {
line = self._createLine(bgcolor, step, self.calcMargin(size, i, step));
corner.appendChild(line);
}
}
this._appendLinesBordered = function(corner, bgcolor, size, step, bdcolor)
{
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);
corner.appendChild(line);
}
line = self._createLine(bdcolor, step, self.calcMargin(size, i, step));
corner.appendChild(line);
}
this._appendLinesBordered2 = function(corner, bgcolor, size, step, bdcolor, bdwidth)
{
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]);
corner.appendChild(line);
}
while (i < size) {
line = self._createLine(bdcolor, step, self.calcMargin2(size, insize, bdsize, i, step)[0]);
corner.appendChild(line);
i += step;
}
}
// }}}
// {{{ マージン計算メソッド
switch (mode) {
case 'line':
case 'linear':
case 'straight':
this.calcMargin = function(size, level, step)
{
return level;
}
this.calcMargin2 = function(size, insize, bdsize, level, step)
{
var x = Math.round(bdsize * (Math.SQRT2 - 1));
return [level - x, bdsize + x];
}
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.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;
}
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);
}
// }}}
// {{{ デフォルト値で作成した要素をキャッシュ
this._defaultTop = this._createTop(this._default);
this._defaultBottom = this._createBottom(this._default);
// }}}
}