我需要使用Javascript从特定的硬编码单词制作标签云。
所以对于这个非常轻量级的简单HTML代码:
<body>
<article></article>
</body>
这个CSS很少:
article {
width: 750px;
height: 750px;
border: 1px solid red;
}
article span {
position: absolute;
}
这些硬编码数据:
var motsHorizontaux = [
'prix',
'transmission',
// ...
'valeur',
'fiscal'
];
var colors = [
'MediumPurple',
'MediumSeaGreen',
// ...
'PaleGreen',
'PaleTurquoise',
];
var fonts = [
'Arial',
'Helvetica',
// ...
'Courrier New',
'Lucida Console'
];
这些Javascript声明:
var random = function(min, max) {
return Math.round(Math.random() * (max - min) + min, 0);
}
Number.prototype.between = function(a, b) {
var min = Math.min.apply(Math, [a, b]),
max = Math.max.apply(Math, [a, b])
;
return this > min && this < max;
};
我想出了这个jQuery代码:
jQuery(function($) {
var $area = $('article')
, minSize = 21
, maxSize = 48
;
for(var i = 0; i < colors.length; i++) {
var $mot = $('<span/>').text(motsHorizontaux[i]).css({
'color': colors[i],
'font-family': fonts[i],
'font-size': random(minSize, maxSize)
});
$mot.appendTo('article');
var topMaxPosition = $area.height() - $mot.height();
var leftMaxPosition = $area.width() - $mot.width();
$mot.css({
'top': random($area.position().top, topMaxPosition),
'left': random($area.position().left, leftMaxPosition)
});
// ...
}
});
所有这些代码输出:
正如你所看到的,话语很好。只有一个缺点,其中一些是相互重叠的。所以为了纠正这个问题,我做了一个尝试,并设法用以下代码将所有单词坐标存储在两个数组中:
$mots = $area.find('> span');
$mots.each(function(j, el) {
var $el = $(el);
var previousTop = $el.position().top;
var previousLeft = $el.position().left;
var previousBottom = previousTop + $el.height();
var previousRight = previousLeft + $el.width();
while(true) {
var newPositionTop = random($area.position().top, topMaxPosition);
var newPositionLeft = random($area.position().left, leftMaxPosition);
var newPositionBottom = newPositionTop + $mot.height();
var newPositionRight = newPositionLeft + $mot.width();
if(
!newPositionTop.between(previousTop, previousBottom) &&
!newPositionBottom.between(previousTop, previousBottom) &&
!newPositionLeft.between(previousLeft, previousRight) &&
!newPositionRight.between(previousLeft, previousRight)
) {
$mot.css({
'top': newPositionTop,
'left': newPositionLeft
});
break;
}
}
});
(此代码段嵌套在外部for() {}
循环中)
但是这仍然使得这些词语相互重叠(即使我不得不承认,也比以前少了)。我认为我有一个误解,因为while(true) {}
循环仅适用于前一个单词($el
),因此删除了之前所有单词的检查(循环中的if( && && && ) {}
)。有人可以帮我修改我的代码吗?
我也为此做了JSFiddle(随意反复运行)。
感谢你们给我的问题带来的关注。
答案 0 :(得分:1)
如果您对云标记使用position:relative,则可能更容易在流程中和流体框内进行管理。
更像是个人意见,而不是建议,以及对js的可怕和快速解决方法。
jQuery(function($) {
var random = function(min, max) {
return Math.round(Math.random() * (max - min) + min, 0);
}
Number.prototype.between = function(a, b) {
var min = Math.min.apply(Math, [a, b]),
max = Math.max.apply(Math, [a, b]);
return this > min && this < max;
};
var motsHorizontaux = [
'prix',
'transmission',
'finances',
'administratif',
'process',
'évaluation',
'performance',
'dirigeant',
'prévisionnel',
'anticipation',
'adaptation',
'suivi',
'contrôle',
'écarts',
'clignotant',
'budget',
'assistance',
'statut',
'social',
'optimisation',
'projet',
'valeur',
'fiscal'
];
var colors = [
'MediumPurple',
'MediumSeaGreen',
'MediumSlateBlue',
'MediumSpringGreen',
'MediumTurquoise',
'SpringGreen',
'SteelBlue',
'Tan',
'Teal',
'Thistle',
'Tomato',
'Turquoise',
'Violet',
'Navy',
'OldLace',
'Olive',
'OliveDrab',
'Orange',
'OrangeRed',
'Orchid',
'PaleGoldenRod',
'PaleGreen',
'PaleTurquoise',
];
var fonts = [
'Arial',
'Helvetica',
'Arial Black',
'Comic Sans MS',
'Impact',
'Charcoal',
'Lucida Sans Unicode',
'Lucida Grande',
'Tahoma',
'Geneva',
'Trebuchet MS',
'Verdana',
'Courrier New',
'Lucida Console'
];
var $area = $('article'),
minSize = 21,
maxSize = 36;
for (var i = 0; i < colors.length; i++) {
var $mot = $('<span/>').text(motsHorizontaux[i]).css({
'color': colors[i],
'font-family': fonts[i],
'font-size': random(minSize, maxSize)
});
$mot.appendTo('article');
var topPosition = $area.height() / 4 - $mot.height();
var leftPosition = $mot.width() /3;
$mot.css({
'top': random(0, topPosition),
'left': random('0', leftPosition)
});
}
var $mots = $area.find('span');
var leftPositions = [];
var topPositions = [];
$mots.each(function(i, el) {
var $el = $(el);
var previousTop = 0;
var previousLeft = 0;
var previousBottom = 0;
var previousRight = 0;
leftPositions[i] = [previousLeft, previousRight];
topPositions[i] = [previousTop, previousBottom];
});
});
&#13;
article {
padding: 2em;
border: 1px solid red;
}
article span {
position: relative;
display: inline-block;
}
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<article></article>
&#13;
答案 1 :(得分:1)
碰撞检测:
function intersectRect(rect1, rect2) {
return !(rect2.left > rect1.right ||
rect2.right < rect1.left ||
rect2.top > rect1.bottom ||
rect2.bottom < rect1.top);
}
您可能需要考虑此插件中的一些有趣代码。 https://github.com/mistic100/jQCloud/blob/master/src/jqcloud.js#L184