古风山水图是一种充满中国传统文化风味和浪漫情致的艺术形式,而如何让这种艺术形式成为现代人们生活中的一部分?今天,我想向大家介绍一款神奇的程序,它可以帮助你在网页上生成任意的古风山水图像。
这个程序是一个用JavaScript编写的小工具,它运用了现代技术和传统艺术,能够在几秒钟内为你创建出一个完美的古风山水图。通过它,你可以看到春夏秋冬四季的山水画,品味古人的风雅情趣,探寻中国文化的博大精深。
这个程序的制作非常简单,只需要在网页上刷新即可生成新的图片,而生成的图片不断地改变,永远不重复。在使用这个程序的过程中,你能够感受到中国传统山水画的画风,来自不同地区的山水布局不同,但每一幅山水画都是独一无二的,一次刷新的过程就是一次欣赏的体验。
这款程序的特别之处在于它不仅有高质量的古风山水图像,还融合了现代艺术元素,加上了人物、树木、水等自然元素,迎合了现代人们的审美需求。每一张生成的山水画都包含着令人驻足的山水、清幽静谧的踏青之景,加之人物的精细设计,令人仿佛置身于古代宫廷之中。
此外,这个程序使用了最新的WebGl技术,几乎可以适配所有的浏览器和设备,不论是电脑、平板还是手机都可以轻松使用。同时,这里也提供了多种尺寸的图片,以供不同需求的用户使用。
总的来说,这款程序不仅在技术上突破了传统山水画在制作上的一些局限性,还将新颖的元素融入到山水之中,使得古风山水图更具现代感。如果你对古风山水感兴趣,欢迎尝试这个程序,体验其中的浪漫、唯美与情怀。
在线Demo地址http://shanshui.toolxq.com/
效果展示
源码分享:
<script id="PolyTools">
var PolyTools = new function() {
this.midPt = function() {
var plist =
arguments.length == 1 ? arguments[0] : Array.apply(null, arguments);
return plist.reduce(
function(acc, v) {
/* if (v == undefined || acc == undefined){
console.log("ERRR");
console.log(plist)
return [0,0]
} */
return [v[0] / plist.length + acc[0], v[1] / plist.length + acc[1]];
},
[0, 0],
);
};
this.triangulate = function(plist, args) {
//return []
var args = args != undefined ? args : {};
var area = args.area != undefined ? args.area : 100;
var convex = args.convex != undefined ? args.convex : false;
var optimize = args.optimize != undefined ? args.optimize : true;
function lineExpr(pt0, pt1) {
var den = pt1[0] - pt0[0];
var m = den == 0 ? Infinity : (pt1[1] - pt0[1]) / den;
var k = pt0[1] - m * pt0[0];
return [m, k];
}
function intersect(ln0, ln1) {
var le0 = lineExpr(...ln0);
var le1 = lineExpr(...ln1);
var den = le0[0] - le1[0];
if (den == 0) {
return false;
}
var x = (le1[1] - le0[1]) / den;
var y = le0[0] * x + le0[1];
function onSeg(p, ln) {
//non-inclusive
return (
Math.min(ln[0][0], ln[1][0]) <= p[0] &&
p[0] <= Math.max(ln[0][0], ln[1][0]) &&
Math.min(ln[0][1], ln[1][1]) <= p[1] &&
p[1] <= Math.max(ln[0][1], ln[1][1])
);
}
if (onSeg([x, y], ln0) && onSeg([x, y], ln1)) {
return [x, y];
}
return false;
}
function ptInPoly(pt, plist) {
var scount = 0;
for (var i = 0; i < plist.length; i++) {
var np = plist[i != plist.length - 1 ? i + 1 : 0];
var sect = intersect(
[plist[i], np],
[pt, [pt[0] + 999, pt[1] + 999]],
);
if (sect != false) {
scount++;
}
}
return scount % 2 == 1;
}
function lnInPoly(ln, plist) {
var lnc = [[0, 0], [0, 0]];
var ep = 0.01;
lnc[0][0] = ln[0][0] * (1 - ep) + ln[1][0] * ep;
lnc[0][1] = ln[0][1] * (1 - ep) + ln[1][1] * ep;
lnc[1][0] = ln[0][0] * ep + ln[1][0] * (1 - ep);
lnc[1][1] = ln[0][1] * ep + ln[1][1] * (1 - ep);
for (var i = 0; i < plist.length; i++) {
var pt = plist[i];
var np = plist[i != plist.length - 1 ? i + 1 : 0];
if (intersect(lnc, [pt, np]) != false) {
return false;
}
}
var mid = PolyTools.midPt(ln);
if (ptInPoly(mid, plist) == false) {
return false;
}
return true;
}
function sidesOf(plist) {
var slist = [];
for (var i = 0; i < plist.length; i++) {
var pt = plist[i];
var np = plist[i != plist.length - 1 ? i + 1 : 0];
var s = Math.sqrt(
Math.pow(np[0] - pt[0], 2) + Math.pow(np[1] - pt[1], 2),
);
slist.push(s);
}
return slist;
}
function areaOf(plist) {
var slist = sidesOf(plist);
var a = slist[0],
b = slist[1],
c = slist[2];
var s = (a + b + c) / 2;
return Math.sqrt(s * (s - a) * (s - b) * (s - c));
}
function sliverRatio(plist) {
var A = areaOf(plist);
var P = sidesOf(plist).reduce(function(m, n) {
return m + n;
}, 0);
return A / P;
}
function bestEar(plist) {
var cuts = [];
for (var i = 0; i < plist.length; i++) {
var pt = plist[i];
var lp = plist[i != 0 ? i - 1 : plist.length - 1];
var np = plist[i != plist.length - 1 ? i + 1 : 0];
var qlist = plist.slice();
qlist.splice(i, 1);
if (convex || lnInPoly([lp, np], plist)) {
var c = [[lp, pt, np], qlist];
if (!optimize) return c;
cuts.push(c);
}
}
var best = [plist, []];
var bestRatio = 0;
for (var i = 0; i < cuts.length; i++) {
var r = sliverRatio(cuts[i][0]);
if (r >= bestRatio) {
best = cuts[i];
bestRatio = r;
}
}
return best;
}
function shatter(plist, a) {
if (plist.length == 0) {
return [];
}
if (areaOf(plist) < a) {
return [plist];
} else {
var slist = sidesOf(plist);
var ind = slist.reduce(
(iMax, x, i, arr) => (x > arr[iMax] ? i : iMax),
0,
);
var nind = (ind + 1) % plist.length;
var lind = (ind + 2) % plist.length;
try {
var mid = PolyTools.midPt([plist[ind], plist[nind]]);
} catch (err) {
console.log(plist);
console.log(err);
return [];
}
return shatter([plist[ind], mid, plist[lind]], a).concat(
shatter([plist[lind], plist[nind], mid], a),
);
}
}
if (plist.length <= 3) {
return shatter(plist, area);
} else {
var cut = bestEar(plist);
return shatter(cut[0], area).concat(
PolyTools.triangulate(cut[1], args),
);
}
};
}();
</script>