Add templates and challenges used in workshop

This commit is contained in:
Aaron Fenyes 2024-10-14 00:25:12 -07:00
commit 6354bc97fe
8 changed files with 1882 additions and 0 deletions

133
challenges/octahedron.html Normal file
View File

@ -0,0 +1,133 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>Octahedron challenge</title>
<meta charset="UTF-8" />
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/jsxgraph/distrib/jsxgraph.css" />
<script type="text/javascript" charset="UTF-8" src="https://cdn.jsdelivr.net/npm/jsxgraph/distrib/jsxgraphcore.js"></script>
</head>
<body>
<h1>Octahedron challenge</h1>
<p>Can you create something like this using <a href="https://jsxgraph.org/docs/symbols/Point3D.html#constructor"><code>Point3D</code></a> and <a href="https://jsxgraph.org/docs/symbols/Polygon3D.html#constructor"><code>Polygon3D</code></a> elements? Dont worry about including the colors; theyre just to emphasize how the polygons fit together.</p>
<p>The <code>create</code> call for <code>Polygon3D</code> isnt documented, but you can look at the polygon sampler for examples.</p>
<div id="octahedron-from-triangles" class="jxgbox" style="width:600px; height:600px"></div>
<!-- a solution to the octahedron challenge -->
<script type="text/javascript">
// to prevent variable name conflicts, we define variables locally using `let`
// and put the code for each board in its own block
{
// create a JSXGraph board and draw a 3D view on it
let board = JXG.JSXGraph.initBoard(
'octahedron-from-triangles',
{
boundingbox: [-8, 8, 8,-8],
axis: false,
showCopyright: false,
showNavigation: false
}
);
let view = board.create(
'view3d',
[[-4.5, -4.5], [9, 9],
[[0, 4], [0, 4], [0, 4]]],
{
xPlaneRear: {fillOpacity: 0.2, gradient: null},
yPlaneRear: {fillOpacity: 0.2, gradient: null},
zPlaneRear: {fillOpacity: 0.2, gradient: null},
depthOrderPoints: true
}
);
// create the vertices of the octahedron
let vertices = [];
coords = [
[1, 2, 2],
[3, 2, 2],
[2, 1, 2],
[2, 3, 2],
[2, 2, 1],
[2, 2, 3]
];
colors = [
'#f08',
'#4f0',
'#f60',
'#0af',
'#40f',
'#fb0'
];
for (i in coords) {
vertices.push(view.create(
'point3d',
coords[i],
{
withLabel: false,
size: 5,
strokeColor: 'none',
fillColor: 'white',
gradientSecondColor: colors[i],
highlightStrokeWidth: 1,
highlightStrokeColor: '#777'
}
));
}
// create the faces of the octahedron
view.create(
'polygon3d',
[vertices[0], vertices[2], vertices[5]],
{
fillColor: '#f85',
fillOpacity: 0.2,
borders: {
strokeWidth: 2,
strokeColor: '#f85',
highlightStrokeColor: '#777'
}
}
);
view.create(
'polygon3d',
[vertices[1], vertices[3], vertices[5]],
{
fillColor: '#af0',
fillOpacity: 0.2,
borders: {
strokeWidth: 2,
strokeColor: '#af0',
highlightStrokeColor: '#777'
}
}
);
view.create(
'polygon3d',
[vertices[0], vertices[3], vertices[4]],
{
fillColor: '#a0f',
fillOpacity: 0.2,
borders: {
strokeWidth: 2,
strokeColor: '#a0f',
highlightStrokeColor: '#777'
}
}
);
view.create(
'polygon3d',
[vertices[1], vertices[2], vertices[4]],
{
fillColor: '#a87',
fillOpacity: 0.2,
borders: {
strokeWidth: 2,
strokeColor: '#a87',
highlightStrokeColor: '#777'
}
}
);
}
</script>
</body>
</html>

View File

@ -0,0 +1,148 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>Sphere contour challenge</title>
<meta charset="UTF-8" />
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/jsxgraph/distrib/jsxgraph.css" />
<script type="text/javascript" charset="UTF-8" src="https://cdn.jsdelivr.net/npm/jsxgraph/distrib/jsxgraphcore.js"></script>
</head>
<body>
<h1>Sphere contour challenge</h1>
<p>Can you create something like this using <a href="https://jsxgraph.org/docs/symbols/Sphere3D.html#constructor"><code>Sphere3D</code></a>, <code>Plane3D</code>, and <a href="https://jsxgraph.org/docs/symbols/IntersectionCircle3D.html"><code>IntersectionCircle3D</code></a> elements? Dont worry about including the colors; theyre just to clarify what happens when you move the center of the sphere.</p>
<p>The <code>visible</code> attribute will come in handy.</p>
<p>Since the <code>create</code> call for <code>Plane3D</code> isnt documented, Ive included an <a href="#create-plane">example</a> below.</p>
<div id="sphere-contours" class="jxgbox" style="width:600px; height:600px"></div>
<h2 id="create-plane">How to create a 3D plane</h2>
<p>A <code>Plane3D</code> is created from a base point and two vectors. The base point can be given either in coordinates or as a <a href="https://jsxgraph.org/docs/symbols/Point3D.html#constructor"><code>Point3D</code></a>. The vectors are given in coordinates.</p>
<div id="plane-example" class="jxgbox" style="width:600px; height:600px"></div>
<!-- a solution to the sphere contour challenge -->
<script type="text/javascript">
// to prevent variable name conflicts, we define variables locally using `let`
// and put the code for each board in its own block
{
// create a JSXGraph board and draw a 3D view on it
let board = JXG.JSXGraph.initBoard(
'sphere-contours',
{
boundingbox: [-8, 8, 8,-8],
axis: false,
showCopyright: false,
showNavigation: false
}
);
let view = board.create(
'view3d',
[[-4.5, -4.5], [9, 9],
[[0, 3], [0, 3], [0, 3]]],
{
xPlaneRear: {fillOpacity: 0.2, gradient: null},
yPlaneRear: {fillOpacity: 0.2, gradient: null},
zPlaneRear: {fillOpacity: 0.2, gradient: null}
}
);
// create a base point
const nCuts = 3*4 + 1;
let cutPositions = Array.from({length: nCuts}, (_, k) => 0.25*k);
let cuttingPlanes = cutPositions.map(
x => view.create(
'plane3d',
[[x, 1.5, 1.5], [0, 1, 0], [0, 0, 1]],
{visible: false}
)
);
// create a center for a sphere
let center = view.create(
'point3d',
[1.5, 1.5, 1.5],
{
withLabel: false,
size: 5,
strokeWidth: 1,
strokeColor: '#300060',
fillColor: 'white',
gradientSecondColor: '#5000a0',
highlightStrokeColor: '#300060'
}
);
// create a sphere whose center is the point `center` and whose radius is 1
let sphere = view.create(
'sphere3d',
[center, 1],
{visible: false}
);
// intersect the sphere with each of the cutting planes
cuttingPlanes.forEach(
(plane, k) => view.create(
'intersectioncircle3d',
[plane, sphere],
{strokeColor: `rgb(${255*k/nCuts}, 0, 255)`}
)
);
}
</script>
<!-- how to create a 3D plane -->
<script type="text/javascript">
// to prevent variable name conflicts, we define variables locally using `let`
// and put the code for each board in its own block
{
// create a JSXGraph board and draw a 3D view on it
let board = JXG.JSXGraph.initBoard(
'plane-example',
{
boundingbox: [-8, 8, 8,-8],
axis: false,
showCopyright: false,
showNavigation: false
}
);
let view = board.create(
'view3d',
[[-4.5, -4.5], [9, 9],
[[0, 3], [0, 3], [0, 3]]],
{
xPlaneRear: {fillOpacity: 0.2, gradient: null},
yPlaneRear: {fillOpacity: 0.2, gradient: null},
zPlaneRear: {fillOpacity: 0.2, gradient: null}
}
);
// create a point
let basePoint = view.create(
'point3d',
[1, 1, 1],
{
withLabel: false,
size: 5,
strokeWidth: 1,
strokeColor: '#300060',
fillColor: 'white',
gradientSecondColor: '#5000a0',
highlightStrokeColor: '#300060'
}
);
// create a plane passing through the point
let plane = view.create(
'plane3d',
[basePoint, [-2, 1, 1], [1, -2, 1]],
{
strokeWidth: 1,
strokeColor: '#00ff80',
strokeOpacity: 0.5,
fillColor: '#00ff80',
fillOpacity: 0.1,
gradient: null
}
);
}
</script>
</body>
</html>

View File

@ -0,0 +1,76 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>3D circle sampler</title>
<meta charset="UTF-8" />
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/jsxgraph/distrib/jsxgraph.css" />
<script type="text/javascript" charset="UTF-8" src="https://cdn.jsdelivr.net/npm/jsxgraph/distrib/jsxgraphcore.js"></script>
</head>
<body>
<h1>3D circle sampler</h1>
<p>A <a href="https://jsxgraph.org/docs/symbols/Circle3D.html"><code>Circle3D</code></a> element is created from a center, a normal vector, and a radius. The center can be given either in coordinates or as a <a href="https://jsxgraph.org/docs/symbols/Point3D.html#constructor"><code>Point3D</code></a>. The normal vector is given in coordinates.</p>
<p>Theres another <a href="https://github.com/jsxgraph/jsxgraph/blob/main/examples/circle3d.html"><code>Circle3D</code> example</a> in the <a href="https://github.com/jsxgraph/jsxgraph/tree/main/examples">examples folder</a> included with the source code.</p>
<div id="circle-board" class="jxgbox" style="width:600px; height:600px"></div>
<script type="text/javascript">
// create a JSXGraph board and draw a 3D view on it
let board = JXG.JSXGraph.initBoard(
'circle-board',
{
boundingbox: [-8, 8, 8,-8],
axis: false,
showCopyright: false,
showNavigation: false
}
);
let view = board.create(
'view3d',
[[-4.5, -4.5], [9, 9],
[[0, 3], [0, 3], [0, 3]]],
{
xPlaneRear: {fillOpacity: 0.2, gradient: null},
yPlaneRear: {fillOpacity: 0.2, gradient: null},
zPlaneRear: {fillOpacity: 0.2, gradient: null}
}
);
// create a point
let center = view.create(
'point3d',
[1.5, 1.5, 1.5],
{
withLabel: false,
strokeWidth: 1,
size: 5,
strokeColor: '#300060',
fillColor: 'white',
gradientSecondColor: '#5000a0',
highlightStrokeColor: '#300060'
}
);
// create some circles that share a center
let normals = [
[1, 1, 1],
[1, -1, 1],
[-1, 1, 1],
[-1, -1, 1]
];
let colors = [
'#f08',
'#f60',
'#fb0',
'#80f'
];
for (i in normals) {
view.create(
'circle3d',
[center, normals[i], 1],
{strokeColor: colors[i]}
);
}
</script>
</body>
</html>

View File

@ -0,0 +1,358 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>3D glider sampler</title>
<meta charset="UTF-8" />
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/jsxgraph/distrib/jsxgraph.css" />
<script type="text/javascript" charset="UTF-8" src="https://cdn.jsdelivr.net/npm/jsxgraph/distrib/jsxgraphcore.js"></script>
</head>
<body>
<h1>3D glider sampler</h1>
<h2>Line glider</h2>
<p>The large point is a glider on the line segment defined by the two small points. This template is based on the <a href="https://github.com/jsxgraph/jsxgraph/blob/main/examples/line3d_glider.html"><code>Line3D</code> glider example</a> in the <a href="https://github.com/jsxgraph/jsxgraph/tree/main/examples">examples folder</a> included with the source code.</p>
<div id="line-glider-board" class="jxgbox" style="width:600px; height:600px"></div>
<h2>Intersection line glider</h2>
<p>The large point is a glider on the line where the two planes intersect.</p>
<div id="intersection-line-glider-board" class="jxgbox" style="width:600px; height:600px"></div>
<h2>Circle glider</h2>
<p>The point is a glider on the circle. This template is based on the <a href="https://github.com/jsxgraph/jsxgraph/blob/main/examples/circle3d_glider.html"><code>Circle3D</code> glider example</a> in the <a href="https://github.com/jsxgraph/jsxgraph/tree/main/examples">examples folder</a> included with the source code.</p>
<p>Right now, the glider gets caught on the point where the circle starts and ends. If you can overcome this limitation, try contributing some code!</p>
<div id="circle-glider-board" class="jxgbox" style="width:600px; height:600px"></div>
<h2>Curve glider</h2>
<p>The point is a glider on the curve. This template is based on the <a href="https://github.com/jsxgraph/jsxgraph/blob/main/examples/curve3d_glider.html"><code>Curve3D</code> glider example</a> in the <a href="https://github.com/jsxgraph/jsxgraph/tree/main/examples">examples folder</a> included with the source code.</p>
<div id="curve-glider-board" class="jxgbox" style="width:600px; height:600px"></div>
<h2>Parametric surface glider</h2>
<p>The point is a glider on the parametric surface. This template is based on the <a href="https://github.com/jsxgraph/jsxgraph/blob/main/examples/parametricsurface3d_glider.html"><code>ParametricSurface3D</code> glider example</a> in the <a href="https://github.com/jsxgraph/jsxgraph/tree/main/examples">examples folder</a> included with the source code.</p>
<div id="surface-glider-board" class="jxgbox" style="width:600px; height:600px"></div>
<!-- line glider -->
<script type="text/javascript">
// to prevent variable name conflicts, we define variables locally using `let`
// and put the code for each board in its own block
{
// create a JSXGraph board and draw a 3D view on it
let board = JXG.JSXGraph.initBoard(
'line-glider-board',
{
boundingbox: [-8, 8, 8,-8],
axis: false,
showCopyright: false,
showNavigation: false
}
);
let view = board.create(
'view3d',
[[-4.5, -4.5], [9, 9],
[[0, 3], [0, 3], [0, 3]]],
{
xPlaneRear: {fillOpacity: 0.2, gradient: null},
yPlaneRear: {fillOpacity: 0.2, gradient: null},
zPlaneRear: {fillOpacity: 0.2, gradient: null}
}
);
// create a line
let p1 = view.create(
'point3d',
[0.5, 0.5, 0.5],
{
withLabel: false,
strokeWidth: 1,
strokeColor: '#300060',
fillColor: 'white',
gradientSecondColor: '#5000a0',
highlightStrokeColor: '#300060'
}
);
let p2 = view.create(
'point3d',
[2.5, 2.5, 2.5],
{
withLabel: false,
strokeWidth: 1,
strokeColor: '#300060',
fillColor: 'white',
gradientSecondColor: '#5000a0',
highlightStrokeColor: '#300060'
}
);
let line = view.create('line3d', [p1, p2]);
// create a glider on the line
let glider = view.create(
'point3d',
[1.5, 1.5, 1.5, line],
{
withLabel: false,
size: 5,
strokeWidth: 1,
strokeColor: '#900060',
fillColor: 'white',
gradientSecondColor: '#fe00a0',
highlightStrokeColor: '#900060'
}
);
}
</script>
<!-- intersection line glider -->
<script type="text/javascript">
// to prevent variable name conflicts, we define variables locally using `let`
// and put the code for each board in its own block
{
// create a JSXGraph board and draw a 3D view on it
let board = JXG.JSXGraph.initBoard(
'intersection-line-glider-board',
{
boundingbox: [-8, 8, 8,-8],
axis: false,
showCopyright: false,
showNavigation: false
}
);
let view = board.create(
'view3d',
[[-4.5, -4.5], [9, 9],
[[0, 3], [0, 3], [0, 3]]],
{
xPlaneRear: {fillOpacity: 0.2, gradient: null},
yPlaneRear: {fillOpacity: 0.2, gradient: null},
zPlaneRear: {fillOpacity: 0.2, gradient: null}
}
);
// create a point and two planes passing though it
let basePoint = view.create(
'point3d',
[1, 1, 1],
{
withLabel: false,
strokeWidth: 1,
strokeColor: '#300060',
fillColor: 'white',
gradientSecondColor: '#5000a0',
highlightStrokeColor: '#300060'
}
);
let planeHoriz = view.create(
'plane3d',
[basePoint, [1, 0, 0], [0, 1, 0]],
{
strokeWidth: 1,
strokeColor: '#0000ff',
strokeOpacity: 0.5,
fillColor: '#0000ff',
fillOpacity: 0.1,
gradient: null
}
);
let planeSloped = view.create(
'plane3d',
[basePoint, [-2, 1, 1], [1, -2, 1]],
{
strokeWidth: 1,
strokeColor: '#00ff80',
strokeOpacity: 0.5,
fillColor: '#00ff80',
fillOpacity: 0.1,
gradient: null
}
);
// create the line where the two planes intersect
let intersectionLine = view.create(
'intersectionline3d',
[planeHoriz, planeSloped],
{
strokeOpacity: 0.5,
highlightStrokeColor: 'black',
highlightStrokeOpacity: 0.5
}
);
// create a glider on the intersection line
let intersectionLineGlider = view.create(
'point3d',
[1.5, 0.5, 1, intersectionLine],
{
withLabel: false,
size: 5,
strokeWidth: 1,
strokeColor: '#900060',
fillColor: 'white',
gradientSecondColor: '#fe00a0',
highlightStrokeColor: '#900060'
}
);
}
</script>
<!-- circle glider -->
<script type="text/javascript">
// to prevent variable name conflicts, we define variables locally using `let`
// and put the code for each board in its own block
{
// create a JSXGraph board and draw a 3D view on it
let board = JXG.JSXGraph.initBoard(
'circle-glider-board',
{
boundingbox: [-8, 8, 8,-8],
axis: false,
showCopyright: false,
showNavigation: false
}
);
let view = board.create(
'view3d',
[[-4.5, -4.5], [9, 9],
[[0, 3], [0, 3], [0, 3]]],
{
xPlaneRear: {fillOpacity: 0.2, gradient: null},
yPlaneRear: {fillOpacity: 0.2, gradient: null},
zPlaneRear: {fillOpacity: 0.2, gradient: null}
}
);
// create a circle
let circle = view.create(
'circle3d',
[[1.5, 1.5, 1.5], [1, 1, 1], 1]
);
// create a glider on the circle
let glider = view.create(
'point3d',
[2, 0.5, 0.5, circle],
{
withLabel: false,
size: 5,
strokeWidth: 1,
strokeColor: '#900060',
fillColor: 'white',
gradientSecondColor: '#fe00a0',
highlightStrokeColor: '#900060'
}
);
}
</script>
<!-- curve glider -->
<script type="text/javascript">
// to prevent variable name conflicts, we define variables locally using `let`
// and put the code for each board in its own block
{
// create a JSXGraph board and draw a 3D view on it
let board = JXG.JSXGraph.initBoard(
'curve-glider-board',
{
boundingbox: [-8, 8, 8,-8],
axis: false,
showCopyright: false,
showNavigation: false
}
);
let view = board.create(
'view3d',
[[-4.5, -4.5], [9, 9],
[[0, 3], [0, 3], [0, 3]]],
{
xPlaneRear: {fillOpacity: 0.2, gradient: null},
yPlaneRear: {fillOpacity: 0.2, gradient: null},
zPlaneRear: {fillOpacity: 0.2, gradient: null}
}
);
// create a 3D curve
let curve = view.create(
'curve3d',
[
(t) => 2.5 + t*t*(-8 + t*t*8),
(t) => 1.5 + t*(5 + t*t*(-20 + t*t*16)),
(t) => 1.5 + t*(-3 + t*t*4),
[-1, 1]
]
);
// create a gilder on the curve
let glider = view.create(
'point3d',
[2.5, 1.5, 1.5, curve],
{
withLabel: false,
size: 5,
strokeWidth: 1,
strokeColor: '#900060',
fillColor: 'white',
gradientSecondColor: '#fe00a0',
highlightStrokeColor: '#900060'
}
);
}
</script>
<!-- parametric surface glider -->
<script type="text/javascript">
// to prevent variable name conflicts, we define variables locally using `let`
// and put the code for each board in its own block
{
// create a JSXGraph board and draw a 3D view on it
let board = JXG.JSXGraph.initBoard(
'surface-glider-board',
{
boundingbox: [-8, 8, 8,-8],
axis: false,
showCopyright: false,
showNavigation: false
}
);
let view = board.create(
'view3d',
[[-4.5, -4.5], [9, 9],
[[0, 2], [0, 2], [0, 2]]],
{
xPlaneRear: {fillOpacity: 0.2, gradient: null},
yPlaneRear: {fillOpacity: 0.2, gradient: null},
zPlaneRear: {fillOpacity: 0.2, gradient: null}
}
);
// create a parametric surface, based on a modified Hammer projection
let rModHammer = (u, v) => Math.sin(u)*Math.cos(v) / Math.sqrt(1 + 3*Math.cos(u)*Math.cos(v));
let zModHammer = (u, v) => Math.sin(v) / Math.sqrt(1 + 3*Math.cos(u)*Math.cos(v));
let twistFn = (u) => Math.PI/2 * Math.tanh(2*u);
let surface = view.create('parametricsurface3d', [
(u, v) => 1 + Math.cos(twistFn(v)) * rModHammer(u, v),
(u, v) => 1 + Math.sin(twistFn(v)) * rModHammer(u, v),
(u, v) => 1 + zModHammer(u, v),
[-Math.PI/3, Math.PI/3],
[-Math.PI/2, Math.PI/2]
], {
strokeColor: '#b080f0',
stepsU: 40,
stepsV: 60
});
// create a glider on the surface
let glider = view.create(
'point3d',
[1, 1, 1, surface],
{
withLabel: false,
size: 5,
strokeWidth: 1,
strokeColor: '#900060',
fillColor: 'white',
gradientSecondColor: '#fe00a0',
highlightStrokeColor: '#900060'
}
);
}
</script>
</body>
</html>

View File

@ -0,0 +1,284 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>3D intersection sampler</title>
<meta charset="UTF-8" />
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/jsxgraph/distrib/jsxgraph.css" />
<script type="text/javascript" charset="UTF-8" src="https://cdn.jsdelivr.net/npm/jsxgraph/distrib/jsxgraphcore.js"></script>
</head>
<body>
<h1>3D intersection sampler</h1>
<h2>Planeplane</h2>
<p>This template is based on the <a href="https://github.com/jsxgraph/jsxgraph/blob/main/examples/intersection_plane_plane.html">planeplane intersection example</a> in the <a href="https://github.com/jsxgraph/jsxgraph/tree/main/examples">examples folder</a> included with the source code.</p>
<div id="plane-plane-board" class="jxgbox" style="width:600px; height:600px"></div>
<h2>Planesphere</h2>
<p>This template is based on the <a href="https://github.com/jsxgraph/jsxgraph/blob/main/examples/intersection_plane_sphere.html">planesphere intersection example</a> in the <a href="https://github.com/jsxgraph/jsxgraph/tree/main/examples">examples folder</a> included with the source code.</p>
<div id="plane-sphere-board" class="jxgbox" style="width:600px; height:600px"></div>
<h2>Spheresphere</h2>
<p>This template is based on the <a href="https://github.com/jsxgraph/jsxgraph/blob/main/examples/intersection_sphere_sphere.html">spheresphere intersection example</a> in the <a href="https://github.com/jsxgraph/jsxgraph/tree/main/examples">examples folder</a> included with the source code.</p>
<div id="sphere-sphere-board" class="jxgbox" style="width:600px; height:600px"></div>
<!-- plane-plane -->
<script type="text/javascript">
// to prevent variable name conflicts, we define variables locally using `let`
// and put the code for each board in its own block
{
// create a JSXGraph board and draw a 3D view on it
let board = JXG.JSXGraph.initBoard(
'plane-plane-board',
{
boundingbox: [-8, 8, 8,-8],
axis: false,
showCopyright: false,
showNavigation: false
}
);
let view = board.create(
'view3d',
[[-4.5, -4.5], [9, 9],
[[0, 3], [0, 3], [0, 3]]],
{
xPlaneRear: {fillOpacity: 0.2, gradient: null},
yPlaneRear: {fillOpacity: 0.2, gradient: null},
zPlaneRear: {fillOpacity: 0.2, gradient: null}
}
);
// create a point and two planes passing though it
let basePoint = view.create(
'point3d',
[1, 1, 1],
{
withLabel: false,
strokeWidth: 1,
size: 5,
strokeColor: '#300060',
fillColor: 'white',
gradientSecondColor: '#5000a0',
highlightStrokeColor: '#300060'
}
);
let planeHoriz = view.create(
'plane3d',
[basePoint, [1, 0, 0], [0, 1, 0]],
{
strokeWidth: 1,
strokeColor: '#0000ff',
strokeOpacity: 0.5,
fillColor: '#0000ff',
fillOpacity: 0.1,
gradient: null
}
);
let planeSloped = view.create(
'plane3d',
[basePoint, [-2, 1, 1], [1, -2, 1]],
{
strokeWidth: 1,
strokeColor: '#00ff80',
strokeOpacity: 0.5,
fillColor: '#00ff80',
fillOpacity: 0.1,
gradient: null
}
);
// create the line where the two planes intersect
let intersectionLine = view.create(
'intersectionline3d',
[planeHoriz, planeSloped],
{
strokeOpacity: 0.5,
highlightStrokeColor: 'black',
highlightStrokeOpacity: 0.5
}
);
}
</script>
<!-- plane-sphere -->
<script type="text/javascript">
// to prevent variable name conflicts, we define variables locally using `let`
// and put the code for each board in its own block
{
// create a JSXGraph board and draw a 3D view on it
let board = JXG.JSXGraph.initBoard(
'plane-sphere-board',
{
boundingbox: [-8, 8, 8,-8],
axis: false,
showCopyright: false,
showNavigation: false
}
);
let view = board.create(
'view3d',
[[-4.5, -4.5], [9, 9],
[[0, 3], [0, 3], [0, 3]]],
{
xPlaneRear: {fillOpacity: 0.2, gradient: null},
yPlaneRear: {fillOpacity: 0.2, gradient: null},
zPlaneRear: {fillOpacity: 0.2, gradient: null}
}
);
// create a plane
let basePoint = view.create(
'point3d',
[4/3, 4/3, 4/3],
{
withLabel: false,
strokeWidth: 1,
size: 5,
strokeColor: '#300060',
fillColor: 'white',
gradientSecondColor: '#5000a0',
highlightStrokeColor: '#300060'
}
);
let plane = view.create(
'plane3d',
[basePoint, [-2, 1, 1], [1, -2, 1]],
{
strokeWidth: 1,
strokeColor: '#00ff80',
strokeOpacity: 0.5,
fillColor: '#00ff80',
fillOpacity: 0.1,
gradient: null
}
);
// create a sphere
let center = view.create(
'point3d',
[1.5, 1.5, 1.5],
{
withLabel: false,
size: 5,
strokeWidth: 1,
strokeColor: '#600030',
fillColor: 'white',
gradientSecondColor: '#a00050',
highlightStrokeColor: '#600030'
}
);
let sphere = view.create(
'sphere3d',
[center, 1],
{
strokeColor: '#0000ff',
strokeOpacity: 0.5,
gradient: 'radial',
gradientSecondColor: '#0000ff',
fillOpacity: 0.2,
}
);
// create the circle where the plane and the sphere intersect
let ixnCircle = view.create(
'intersectioncircle3d',
[plane, sphere],
{
strokeColor: 'black',
strokeOpacity: 0.5
}
);
}
</script>
<!-- sphere-sphere -->
<script type="text/javascript">
// to prevent variable name conflicts, we define variables locally using `let`
// and put the code for each board in its own block
{
// create a JSXGraph board and draw a 3D view on it
let board = JXG.JSXGraph.initBoard(
'sphere-sphere-board',
{
boundingbox: [-8, 8, 8,-8],
axis: false,
showCopyright: false,
showNavigation: false
}
);
let view = board.create(
'view3d',
[[-4.5, -4.5], [9, 9],
[[0, 3], [0, 3], [0, 3]]],
{
xPlaneRear: {fillOpacity: 0.2, gradient: null},
yPlaneRear: {fillOpacity: 0.2, gradient: null},
zPlaneRear: {fillOpacity: 0.2, gradient: null}
}
);
// create two centers
let center1 = view.create(
'point3d',
[1, 1.5, 1.5],
{
withLabel: false,
size: 5,
strokeWidth: 1,
strokeColor: '#600030',
fillColor: 'white',
gradientSecondColor: '#a00050',
highlightStrokeColor: '#600030'
}
);
let center2 = view.create(
'point3d',
[2, 1.5, 1.5],
{
withLabel: false,
size: 5,
strokeWidth: 1,
strokeColor: '#600030',
fillColor: 'white',
gradientSecondColor: '#a00050',
highlightStrokeColor: '#600030'
}
);
// create two spheres
let sphere1 = view.create(
'sphere3d',
[center1, 0.75],
{
strokeColor: '#0000ff',
strokeOpacity: 0.5,
fillColor: 'white',
fillOpacity: 0.2,
gradientSecondColor: '#0000ff'
}
);
let sphere2 = view.create(
'sphere3d',
[center2, 0.75],
{
strokeColor: '#00ff80',
strokeOpacity: 0.5,
fillColor: 'white',
fillOpacity: 0.2,
gradientSecondColor: '#00ff80'
}
);
// create the circle where the spheres intersect
let ixnCircle = view.create(
'intersectioncircle3d',
[sphere1, sphere2],
{
strokeColor: 'black',
strokeOpacity: 0.5
}
);
}
</script>
</body>
</html>

View File

@ -0,0 +1,404 @@
<!DOCTYPE html>
<html>
<head>
<title>3D polygon sampler</title>
<meta charset="UTF-8" />
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/jsxgraph/distrib/jsxgraph.css" />
<script type="text/javascript" charset="UTF-8" src="https://cdn.jsdelivr.net/npm/jsxgraph/distrib/jsxgraphcore.js"></script>
</head>
<body>
<h1>3D polygon sampler</h1>
<h2>Creating a polygon</h2>
<p>A polygon is created from a list of vertices. Each vertex is given either in coordinates or as a <a href="https://jsxgraph.org/docs/symbols/Point3D.html#constructor"><code>Point3D</code></a> element. The vertices that are created from coordinates are styled according to the <code>vertices</code> attribute. The edges of the polygon are styled according to the <code>borders</code> attribute.</p>
<p>To make the layout of the vertices easier to see, Ive set the views <code>depthOrderPoints</code> attribute to <code>true</code>.
<div id="polygon-homog-board" class="jxgbox" style="width:600px; height:600px"></div>
<h2>Mixing coordinates and <code>Point3D</code> elements</h2>
<p>This example shows how you can mix coordinates and <a href="https://jsxgraph.org/docs/symbols/Point3D.html#constructor"><code>Point3D</code></a> elements in a polygons vertex list.</p>
<div id="polygon-mixed-board" class="jxgbox" style="width:600px; height:600px"></div>
<h2>Filling a polygon</h2>
<p>You can set the fill and opacity of a 3D polygon just like you would with a 2D polygon. I recommend only filling polygons that are guaranteed to stay planar. In this example, the polygons are always planar because theyre triangles.</p>
<div id="planar-fill-board" class="jxgbox" style="width:600px; height:600px"></div>
<h2>The pitalls of filling a non-planar polygon</h2>
<p>Make the polygon below non-planar by dragging its vertices. This will probably make the fill look really weird from certain angles.</p>
<div id="non-planar-fill-board" class="jxgbox" style="width:600px; height:600px"></div>
<!-- creating a polygon -->
<script type="text/javascript">
// to prevent variable name conflicts, we define variables locally using `let`
// and put the code for each board in its own block
{
// create a JSXGraph board and draw a 3D view on it
let board = JXG.JSXGraph.initBoard(
'polygon-homog-board',
{
boundingbox: [-8, 8, 8,-8],
axis: false,
showCopyright: false,
showNavigation: false
}
);
let view = board.create(
'view3d',
[[-4.5, -4.5], [9, 9],
[[0, 3], [0, 3], [0, 3]]],
{
xPlaneRear: {fillOpacity: 0.2, gradient: null},
yPlaneRear: {fillOpacity: 0.2, gradient: null},
zPlaneRear: {fillOpacity: 0.2, gradient: null},
depthOrderPoints: true
}
);
// create a list of individually styled Point3D elements to use as the
// vertices of a polygon
let vertices1 = [];
coords1 = [
[2, 1, 1],
[2, 2, 1],
[1, 2, 1],
[1, 2, 2],
[1, 1, 2],
[1, 1, 1]
];
colors1 = [
'orangered',
'gold',
'mediumseagreen',
'darkturquoise',
'purple',
'deeppink'
];
for (i in coords1) {
vertices1.push(view.create(
'point3d',
coords1[i],
{
withLabel: false,
size: 5,
strokeColor: 'none',
fillColor: 'white',
gradientSecondColor: colors1[i],
highlightStrokeWidth: 1,
highlightStrokeColor: '#777'
}
));
}
// create a polygon from a list of vertices (given as Point3D elements)
let polygon1 = view.create(
'polygon3d',
vertices1,
{
borders: {
strokeColor: '#777',
highlightStrokeColor: '#999'
}
}
);
// create a polygon from a list of vertices (given in coordinates)
let coords2 = [
[0.5, 1.5, 1.5],
[1.5, 1.5, 1.5],
[1.5, 2.5, 1.5],
[0.5, 2.5, 1.5]
];
let polygon2 = view.create(
'polygon3d',
coords2,
{
vertices: {
withLabel: false,
strokeColor: 'none',
fillColor: 'white',
gradientSecondColor: '#444',
highlightStrokeWidth: 1,
highlightStrokeColor: 'black'
},
borders: {
strokeColor: 'black',
highlightStrokeColor: 'gray'
}
}
);
}
</script>
<!-- mixing coordinates and Point3D elements -->
<script type="text/javascript">
// to prevent variable name conflicts, we define variables locally using `let`
// and put the code for each board in its own block
{
// create a JSXGraph board and draw a 3D view on it
let board = JXG.JSXGraph.initBoard(
'polygon-mixed-board',
{
boundingbox: [-8, 8, 8,-8],
axis: false,
showCopyright: false,
showNavigation: false
}
);
let view = board.create(
'view3d',
[[-4.5, -4.5], [9, 9],
[[0, 3], [0, 3], [0, 3]]],
{
xPlaneRear: {fillOpacity: 0.2, gradient: null},
yPlaneRear: {fillOpacity: 0.2, gradient: null},
zPlaneRear: {fillOpacity: 0.2, gradient: null},
depthOrderPoints: true
}
);
// create a list of individually styled Point3D elements to use as some
// vertices of a polygon
let vertices1 = [];
coords1 = [
[2, 1, 1],
[2, 2, 1],
[1, 2, 1],
[1, 2, 2],
[1, 1, 2],
[1, 1, 1]
];
colors1 = [
'orangered',
'gold',
'mediumseagreen',
'darkturquoise',
'purple',
'deeppink'
];
for (i in coords1) {
vertices1.push(view.create(
'point3d',
coords1[i],
{
withLabel: false,
size: 5,
strokeColor: 'none',
fillColor: 'white',
gradientSecondColor: colors1[i],
highlightStrokeWidth: 1,
highlightStrokeColor: '#777'
}
));
}
// list the coordinates of the other vertices of the polygon
let coords2 = [
[0.5, 1.5, 1.5],
[1.5, 1.5, 1.5],
[1.5, 2.5, 1.5],
[0.5, 2.5, 1.5]
];
// create a polygon from a list of vertices (some given in coordinates, and
// others given as Point3D elements)
let polygon = view.create(
'polygon3d',
vertices1.slice(0, 3).concat(coords2, vertices1.slice(3, 6)),
{
vertices: {
withLabel: false,
strokeColor: 'none',
fillColor: 'white',
gradientSecondColor: '#444',
highlightStrokeWidth: 1,
highlightStrokeColor: 'black'
},
borders: {
strokeColor: 'black',
highlightStrokeColor: 'gray'
}
}
);
}
</script>
<!-- filling a polygon -->
<script type="text/javascript">
// to prevent variable name conflicts, we define variables locally using `let`
// and put the code for each board in its own block
{
// create a JSXGraph board and draw a 3D view on it
let board = JXG.JSXGraph.initBoard(
'planar-fill-board',
{
boundingbox: [-8, 8, 8,-8],
axis: false,
showCopyright: false,
showNavigation: false
}
);
let view = board.create(
'view3d',
[[-4.5, -4.5], [9, 9],
[[0, 3], [0, 3], [0, 3]]],
{
xPlaneRear: {fillOpacity: 0.2, gradient: null},
yPlaneRear: {fillOpacity: 0.2, gradient: null},
zPlaneRear: {fillOpacity: 0.2, gradient: null},
depthOrderPoints: true
}
);
// create a list of individually styled Point3D elements to use as polygon
// vertices
let vertices = [];
coords = [
[2, 0.5, 0.5],
[0.5, 2, 0.5],
[0.5, 0.5, 2],
[0.5, 1.25, 1.25],
[1.25, 0.5, 1.25],
[1.25, 1.25, 0.5]
];
colors = [
'#f08',
'#fb0',
'#0af',
'#4f0',
'#80f',
'#f60'
];
for (i in coords) {
vertices.push(view.create(
'point3d',
coords[i],
{
withLabel: false,
size: 5,
strokeColor: 'none',
fillColor: 'white',
gradientSecondColor: colors[i],
highlightStrokeWidth: 1,
highlightStrokeColor: '#777'
}
));
}
// create some filled triangles
view.create(
'polygon3d',
[vertices[0], vertices[5], vertices[4]],
{
fillColor: '#f85',
fillOpacity: 0.4,
borders: {strokeColor: 'none'}
}
);
view.create(
'polygon3d',
[vertices[1], vertices[3], vertices[5]],
{
fillColor: '#af0',
fillOpacity: 0.4,
borders: {strokeColor: 'none'}
}
);
view.create(
'polygon3d',
[vertices[2], vertices[3], vertices[4]],
{
fillColor: '#64f',
fillOpacity: 0.4,
borders: {strokeColor: 'none'}
}
);
view.create(
'polygon3d',
[vertices[3], vertices[4], vertices[5]],
{
fillColor: '#a87',
fillOpacity: 0.4,
borders: {strokeColor: 'none'}
}
);
}
</script>
<!-- the pitfalls of filling a non-planar polygon -->
<script type="text/javascript">
// to prevent variable name conflicts, we define variables locally using `let`
// and put the code for each board in its own block
{
// create a JSXGraph board and draw a 3D view on it
let board = JXG.JSXGraph.initBoard(
'non-planar-fill-board',
{
boundingbox: [-8, 8, 8,-8],
axis: false,
showCopyright: false,
showNavigation: false
}
);
let view = board.create(
'view3d',
[[-4.5, -4.5], [9, 9],
[[0, 3], [0, 3], [0, 3]]],
{
xPlaneRear: {fillOpacity: 0.2, gradient: null},
yPlaneRear: {fillOpacity: 0.2, gradient: null},
zPlaneRear: {fillOpacity: 0.2, gradient: null},
depthOrderPoints: true
}
);
// create a list of individually styled Point3D elements to use as polygon
// vertices
let vertices = [];
coords = [
[2, 0.5, 0.5],
[0.5, 2, 0.5],
[0.5, 0.5, 2],
[0.5, 1.25, 1.25],
[1.25, 0.5, 1.25],
[1.25, 1.25, 0.5]
];
colors = [
'#f08',
'#fb0',
'#0af',
'#4f0',
'#80f',
'#f60'
];
for (i in coords) {
vertices.push(view.create(
'point3d',
coords[i],
{
withLabel: false,
size: 5,
strokeColor: 'none',
fillColor: 'white',
gradientSecondColor: colors[i],
highlightStrokeWidth: 1,
highlightStrokeColor: '#777'
}
));
}
// create a filled polygon that can become non-planar
view.create(
'polygon3d',
[vertices[0], vertices[5], vertices[1], vertices[3], vertices[2], vertices[4]],
{
fillColor: '#a87',
fillOpacity: 0.4,
borders: {strokeColor: 'none'}
}
);
}
</script>
</body>
</html>

View File

@ -0,0 +1,227 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>Sphere sampler</title>
<meta charset="UTF-8" />
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/jsxgraph/distrib/jsxgraph.css" />
<script type="text/javascript" charset="UTF-8" src="https://cdn.jsdelivr.net/npm/jsxgraph/distrib/jsxgraphcore.js"></script>
</head>
<body>
<h1>Sphere sampler</h1>
<h2>Creating spheres</h2>
<p>
Right now, there are two ways to create a <a href="https://jsxgraph.org/docs/symbols/Sphere3D.html#constructor"><code>Sphere3D</code></a>:
<ul>
<li>Give its center and its radius.</li>
<li>Give its center a point on it.</li>
</ul>
Point data can be given either in coordinates or as a <a href="https://jsxgraph.org/docs/symbols/Point3D.html#constructor"><code>Point3D</code></a>.
</p>
<div id="creating-spheres-board" class="jxgbox" style="width:600px; height:600px"></div>
<h2>Styling spheres</h2>
<p>Here are some styling options for spheres and the points that define them.</p>
<div id="styling-spheres-board" class="jxgbox" style="width:600px; height:600px"></div>
<!-- creating spheres -->
<script type="text/javascript">
// to prevent variable name conflicts, we define variables locally using `let`
// and put the code for each board in its own block
{
// create a JSXGraph board and draw a 3D view on it
let board = JXG.JSXGraph.initBoard(
'creating-spheres-board',
{
boundingbox: [-8, 8, 8,-8],
axis: false,
showcopyright: false,
shownavigation: false
}
);
let view = board.create(
'view3d',
[[-4.5, -4.5], [9, 9],
[[0, 4], [0, 4], [0, 4]]],
{
xPlaneRear: {fillOpacity: 0.2, gradient: null},
yPlaneRear: {fillOpacity: 0.2, gradient: null},
zPlaneRear: {fillOpacity: 0.2, gradient: null}
}
);
// create a sphere by giving:
// - its center (in coordinates)
// - its radius
view.create(
'sphere3d',
[[3, 1, 2], 0.8]
);
// create a sphere by giving:
// - its center (in coordinates)
// - a point on it (in coordinates)
view.create(
'sphere3d',
[[3, 3, 2], [3, 3, 2.8]]
);
// create a sphere by giving:
// - its center (in coordinates)
// - a point on it (as a Point3D)
let sharedPoint = view.create(
'point3d',
[1, 2, 2]
);
view.create(
'sphere3d',
[[1, 1, 2], sharedPoint]
);
// create a sphere by giving:
// - its center (as a Point3D)
// - a point on it (as a Point3D)
let center = view.create(
'point3d',
[1, 3, 2]
);
view.create(
'sphere3d',
[center, sharedPoint]
);
}
</script>
<!-- styling demo -->
<script type="text/javascript">
// to prevent variable name conflicts, we define variables locally using `let`
// and put the code for each board in its own block
{
// create a JSXGraph board and draw a 3D view on it
let board = JXG.JSXGraph.initBoard(
'styling-spheres-board',
{
boundingbox: [-8, 8, 8,-8],
axis: false,
showCopyright: false,
showNavigation: false
}
);
let view = board.create(
'view3d',
[[-4.5, -4.5], [9, 9],
[[0, 4], [0, 4], [0, 4]]],
{
xPlaneRear: {fillOpacity: 0.2, gradient: null},
yPlaneRear: {fillOpacity: 0.2, gradient: null},
zPlaneRear: {fillOpacity: 0.2, gradient: null}
}
);
// create a sphere with a custom stroke style and main color. the center is
// created at the given coordinates, with the style specified in the
// `center` attribute
view.create(
'sphere3d',
[[3, 1, 2], 0.8],
{
strokeColor: '#0080ff',
strokeOpacity: 0.5,
gradientSecondColor: '#0080ff',
center: {
size: 5,
strokeWidth: 1,
strokeColor: '#0000c0',
fillColor: 'white',
gradientSecondColor: '#0000ff',
highlightStrokeColor: '#0000c0',
withLabel: false
}
}
);
// create a sphere with a custom stroke style and main color. the center and
// a point on the sphere are created at the given coordinates, with the
// styles specified in the `center` and `point` attributes
view.create(
'sphere3d',
[[3, 3, 2], [3, 3, 2.8]],
{
strokeColor: '#4000ff',
strokeOpacity: 0.5,
gradientSecondColor: '#4000ff',
center: {
size: 5,
strokeWidth: 1,
strokeColor: '#9000c0',
fillColor: 'white',
gradientSecondColor: '#c000ff',
highlightStrokeColor: '#9000c0',
withLabel: false
},
point: {
strokeWidth: 1,
strokeColor: '#c06000',
fillColor: 'white',
gradientSecondColor: '#ff8000',
highlightStrokeColor: '#c06000',
withLabel: false
}
}
);
// create a sphere with a custom stroke style, main color, and highlight
// color
view.create(
'sphere3d',
[[1, 1, 2], 0.8],
{
strokeColor: '#4000ff',
strokeOpacity: 0.5,
fillColor: '#ff00ff',
gradientSecondColor: '#4000ff',
center: {
size: 5,
strokeWidth: 1,
strokeColor: '#9000c0',
fillColor: 'white',
gradientSecondColor: '#c000ff',
highlightStrokeColor: '#9000c0',
withLabel: false
}
}
);
// create a sphere with a custom stroke style, main color, and opacity
view.create(
'sphere3d',
[[1, 3, 2], 0.8],
{
/*strokeColor: '#0000ff',
strokeOpacity: 0.5,
fillColor: 'white',
gradient: 'radial',
gradientSecondColor: '#0000ff',
gradientFX: 0.7,
gradientFY: 0.3,
fillOpacity: 0.2,*/
strokeColor: '#0080ff',
strokeOpacity: 0.5,
gradientSecondColor: '#0080ff',
fillOpacity: 0.8,
center: {
size: 5,
strokeWidth: 1,
strokeColor: '#0000c0',
fillColor: 'white',
gradientSecondColor: '#0000ff',
highlightStrokeColor: '#0000c0',
withLabel: false
}
}
);
}
</script>
</body>
</html>

252
templates/view-demo.html Normal file
View File

@ -0,0 +1,252 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>View options demo</title>
<meta charset="UTF-8" />
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/jsxgraph/distrib/jsxgraph.css" />
<script type="text/javascript" charset="UTF-8" src="https://cdn.jsdelivr.net/npm/jsxgraph/distrib/jsxgraphcore.js"></script>
</head>
<body>
<h1>View options demo</h1>
<h2>Central projection; depth ordering for points</h2>
<p>
This demo shows how the new <code>projection</code> and <code>depthOrderPoints</code> options of a <code>View3D</code> affect the view. Use the controls to:
<ul>
<li>Switch between parallel and central projection (<code>projection</code> set to <code>'parallel'</code> and <code>'central'</code>, respectively).</li>
<li>Switch depth ordering of points on and off (<code>depthOrderPoints</code> set to <code>true</code> or <code>false</code>).
</ul>
To see what depth ordering does, rotate the view to make two points overlap, and then rotate again to switch which point is in front.
</p>
<div>
<label for="proj">Projection:</label>
<select id="proj">
<option value="parallel">Parallel</option>
<option value="central">Central</option>
</select>
</div>
<div>
<input id="depth-ordering-ctl" type="checkbox" />
<label for="depth-ordering-ctl">Depth-order points</label>
</div>
<div id="proj-depth-board" class="jxgbox" style="width:600px; height:600px"></div>
<h2>Virtual trackball; bank angle slider</h2>
<p>
In the default orientation control mode, dragging the mouse changes the Tait-Bryan angles of the camera.
<ul>
<li>Dragging horizontally changes the azimuth.</li>
<li>Dragging vertically changes the elevation.</li>
<li>As of <a href="https://jsxgraph.org/wp/2024-06-28-release-of-version-1.9.2/">version 1.9.2</a>, doing a scroll gesture with the mouse button down changes the bank angle.</li>
</ul>
The Tait-Bryan angles can also be controlled with sliders, which are hidden by default. To show them, set the following attributes:
<ul>
<li><code>az: {slider: {visible: true}}</code></li>
<li><code>el: {slider: {visible: true}}</code></li>
<li><code>bank: {slider: {visible: true}}</code> (as of <a href="https://jsxgraph.org/wp/2024-06-28-release-of-version-1.9.2/">version 1.9.2</a>)</li>
</ul>
</p>
<p>
<a href="https://jsxgraph.org/wp/2024-06-28-release-of-version-1.9.2/">Version 1.9.2</a> introduces a new orientation control mode: the <em>virtual trackball</em>. In this mode, dragging from near the center of the board rolls the view along the drag direction, while dragging from near the edge of the board rotates the view in the plane of the board. These two motions transition smoothly into each other as the drag start position changes. To enable the virtual trackball, set the <code>trackball</code> attribute of the <code>View3D</code> to <code>{enabled: true}</code>.
</p>
<p>
This demo is based on the <a href="https://github.com/jsxgraph/jsxgraph/blob/main/examples/trackball.html">virtual trackball example</a> in the <a href="https://github.com/jsxgraph/jsxgraph/tree/main/examples">examples folder</a> included with the source code.
</p>
</p>
<div>
<label for="ori-ctl">Orientation control:</label>
<select id="ori-ctl">
<option value="angles">TaitBryan angles</option>
<option value="trackball">Virtual trackball</option>
</select>
</div>
<div id="trackball-board" class="jxgbox" style="width:600px; height:600px"></div>
<!-- projection style; and depth ordering for points -->
<script type="text/javascript">
// to prevent variable name conflicts, we define variables locally using `let`
// and put the code for each board in its own block
{
// create a JSXGraph board and draw a 3D view on it
let board = JXG.JSXGraph.initBoard(
'proj-depth-board',
{
boundingbox: [-8, 8, 8,-8],
axis: false,
showCopyright: false,
showNavigation: false
}
);
let view = board.create(
'view3d',
[[-4.5, -4.5], [9, 9],
[[0, 3], [0, 3], [0, 3]]],
{
xPlaneRear: {fillOpacity: 0.2, gradient: null},
yPlaneRear: {fillOpacity: 0.2, gradient: null},
zPlaneRear: {fillOpacity: 0.2, gradient: null}
}
);
// create a list of individually styled Point3D elements to use as the
// vertices of a polygon
let vertices1 = [];
coords1 = [
[2, 1, 1],
[2, 2, 1],
[1, 2, 1],
[1, 2, 2],
[1, 1, 2],
[1, 1, 1]
];
colors1 = [
'orangered',
'gold',
'mediumseagreen',
'darkturquoise',
'purple',
'deeppink'
];
for (i in coords1) {
vertices1.push(view.create(
'point3d',
coords1[i],
{
withLabel: false,
size: 5,
strokeColor: 'none',
fillColor: 'white',
gradientSecondColor: colors1[i],
highlightStrokeWidth: 1,
highlightStrokeColor: '#777'
}
));
}
// create a polygon from a list of vertices (given as Point3D elements)
let polygon1 = view.create(
'polygon3d',
vertices1,
{
borders: {
strokeColor: '#777',
highlightStrokeColor: '#999'
}
}
);
// create a polygon from a list of vertices (given in coordinates)
let coords2 = [
[0.5, 1.5, 1.5],
[1.5, 1.5, 1.5],
[1.5, 2.5, 1.5],
[0.5, 2.5, 1.5]
];
let polygon2 = view.create(
'polygon3d',
coords2,
{
vertices: {
withLabel: false,
strokeColor: 'none',
fillColor: 'white',
gradientSecondColor: '#444',
highlightStrokeWidth: 1,
highlightStrokeColor: 'black'
},
borders: {
strokeColor: 'black',
highlightStrokeColor: 'gray'
}
}
);
// switch between parallel and central projection
proj = document.querySelector('#proj');
function inputProjectionType() {
view.setAttribute({'projection': proj.value});
}
proj.addEventListener('input', inputProjectionType);
inputProjectionType();
// switch depth ordering of points on and off
let depthOrderingCtl = document.querySelector('#depth-ordering-ctl');
function inputDepthOrderingCtl() {
view.setAttribute({'depthOrderPoints': depthOrderingCtl.checked});
}
depthOrderingCtl.addEventListener('input', inputDepthOrderingCtl);
inputDepthOrderingCtl();
}
</script>
<!-- virtual trackball; bank angle slider -->
<script type="text/javascript">
// to prevent variable name conflicts, we define variables locally using `let`
// and put the code for each board in its own block
{
// create a JSXGraph board and draw a 3D view on it
let board = JXG.JSXGraph.initBoard(
'trackball-board',
{
boundingbox: [-8, 8, 8,-8],
axis: false,
showCopyright: false,
showNavigation: false
}
);
let view = board.create(
'view3d',
[[-4.5, -4.5], [9, 9],
[[0, 5], [0, 5], [0, 5]]],
{
xPlaneRear: {fillOpacity: 0.2, gradient: null},
yPlaneRear: {fillOpacity: 0.2, gradient: null},
zPlaneRear: {fillOpacity: 0.2, gradient: null},
axis: true,
axesPosition: 'center',
xAxis: {
name: 'x',
strokeColor: 'red',
strokeWidth: 3,
withLabel: true,
label:{position: 'last', autoPosition: true}
},
yAxis: {
name: 'y',
strokeColor: 'green',
strokeWidth: 3,
withLabel: true,
label:{position: 'last', autoPosition: true}
},
zAxis: {
name: 'z',
strokeColor: 'blue',
strokeWidth: 3,
withLabel: true,
label:{position: 'last', autoPosition: true}
},
projection: 'central',
az: {
slider: {visible: true, min: -0.75*Math.PI, max: 1.25*Math.PI}
},
el: {
slider: {visible: true}
},
bank: {
slider: {visible: true, min: -(4/3)*Math.PI, max: (2/3)*Math.PI}
}
}
);
// switch between virtual trackball navigation and Tait-Bryan angle navigation
let ori_ctl = document.querySelector('#ori-ctl');
function inputOriCtl() {
view.setAttribute({'trackball': {enabled: ori_ctl.value === 'trackball'}});
}
ori_ctl.addEventListener('input', inputOriCtl);
inputOriCtl();
}
</script>
</body>
</html>