I've found this question asked before but the solutions offered did not solve my issue. I've tried creating this project in only #react-three but I've added vanilla three and cannon to supplement my #react-three (therefor my code is convoluted).
This error only occurs on rounded TextGeometry and I've been able to duplicate the error in a Codesandbox example.
I've tried:
Adding and removing computeBoundingBox() and computeBoundingSphere()
Removing the array from around my position const
I've added width segment and height segment parameters to PlaneBufferGeometry
Incorporating code I found in examples that had rounded TextGeometry
Here is the function for the TextGeometry:
// const position = [pos.x / 4, pos.y / 8, 2];
export function Font({ letter, position: initialPosition }) {
const { size, viewport } = useThree();
const [position, setPosition] = useState(initialPosition);
const [quaternion, setQuaternion] = useState([0, 0, 0, 0]);
const aspect = size.width / viewport.width;
const font = new FontLoader().parse(Roboto);
const textOptions = {
font,
size: 1,
height: 0,
curveSegments: 0,
bevelEnabled: true,
bevelThickness: 0.3,
bevelSize: 0.1,
bevelOffset: -0.01,
bevelSegments: 12
};
const letterGeom = new TextGeometry(
letter,
textOptions
);
letterGeom.computeBoundingBox();
letterGeom.computeBoundingSphere();
const letterMat = new THREE.MeshLambertMaterial();
const letterMesh = new THREE.Mesh(letterGeom, letterMat);
letterMesh.size = letterMesh.geometry.boundingBox.getSize(new THREE.Vector3());
const box = new CANNON.Box(new CANNON.Vec3().copy(letterMesh.size).scale(0.5));
const { center } = letterMesh.geometry.boundingSphere;
const { ref, body } = useCannon({ bodyProps: { mass: 10 } }, body => {
body.addShape(box, new CANNON.Vec3(center.x, center.y, center.z));
body.position.set(...position);
}, []);
const bind = useDrag(({ offset: [,], xy: [x, y], first, last }) => {
if (first) {
body.mass = 0;
body.updateMassProperties();
} else if (last) {
body.mass = 10000;
body.updateMassProperties();
}
body.position.set((x - size.width / 2) / aspect, -(y - size.height / 2) / aspect, -0.7);
}, { pointerEvents: true });
useFrame(() => {
const deltaX = Math.abs(body.position.x - position[0]);
const deltaY = Math.abs(body.position.y - position[1]);
const deltaZ = Math.abs(body.position.z - position[2]);
if (deltaX > 0.001 || deltaY > 0.001 || deltaZ > 0.001) {
setPosition(body.position.clone().toArray());
}
const bodyQuaternion = body.quaternion.toArray();
const quaternionDelta = bodyQuaternion.map((n, idx) => Math.abs(n - quaternion[idx]))
.reduce((acc, curr) => acc + curr);
if (quaternionDelta > 0.01) {
setQuaternion(body.quaternion.toArray());
}
});
// extend TextGeometry to THREE
extend({ TextGeometry })
return (
<mesh ref={ref} castShadow position={position} quaternion={quaternion} {...bind()}
onClick={e => {
e.stopPropagation();
}}
>
<textGeometry attach='geometry' args={[letter, textOptions]} />
<meshLambertMaterial attach='material' color="lightcoral" />
</mesh>
);
}
Here is the error in console:
THREE.BufferGeometry.computeBoundingSphere(): Computed radius is NaN. The "position" attribute is likely to have NaN values.
TextGeometry {isBufferGeometry: true, uuid: '49e5c324-9134-407e-962f-6ff170a6afb7', name: '', type: 'TextGeometry', index: null, …}
attributes:
normal: BufferAttribute {isBufferAttribute: true, name: '', array: Float32Array(12852), itemSize: 3, count: 4284, …}
position: Float32BufferAttribute
array: Float32Array(12852) [NaN, NaN, -0.30000001192092896, NaN, NaN, -0.30000001192092896, NaN, NaN, -0.30000001192092896, NaN, NaN, -0.30000001192092896, NaN, NaN, -0.30000001192092896, NaN, NaN, -0.30000001192092896, NaN, NaN, -0.30000001192092896, NaN, NaN, -0.30000001192092896, NaN, NaN, -0.30000001192092896, NaN, NaN, -0.30000001192092896, 0.0689999982714653, 0.4771421253681183, -0.30000001192092896, NaN, NaN, -0.30000001192092896, NaN, NaN, -0.30000001192092896, NaN, NaN, -0.30000001192092896, NaN, NaN, -0.30000001192092896, NaN, NaN, -0.30000001192092896, NaN, NaN, -0.30000001192092896, NaN, NaN, -0.30000001192092896, NaN, NaN, -0.30000001192092896, NaN, NaN, -0.30000001192092896, NaN, NaN, -0.30000001192092896, NaN, NaN, -0.30000001192092896, 0.8880000114440918, 0.5088578462600708, -0.30000001192092896, NaN, NaN, -0.30000001192092896, NaN, NaN, -0.30000001192092896, NaN, NaN, -0.30000001192092896, NaN, NaN, -0.30000001192092896, NaN, NaN, -0.30000001192092896, NaN, NaN, -0.30000001192092896, NaN, NaN, -0.30000001192092896, NaN, NaN, -0.30000001192092896, NaN, NaN, -0.30000001192092896, NaN, NaN, -0.30000001192092896, NaN, …]
count: 4284
isBufferAttribute: true
itemSize: 3
name: ""
normalized: false
updateRange: {offset: 0, count: -1}
usage: 35044
version: 0
[[Prototype]]: BufferAttribute
uv: Float32BufferAttribute {isBufferAttribute: true, name: '', array: Float32Array(8568), itemSize: 2, count: 4284, …}
[[Prototype]]: Object
boundingBox: Box3 {isBox3: true, min: Vector3, max: Vector3}
boundingSphere: Sphere
center: Vector3
x: 0.47850000485777855
y: 0.49300000071525574
z: 0
[[Prototype]]: Object
radius: NaN
[[Prototype]]: Object
drawRange: {start: 0, count: Infinity}
groups: (2) [{…}, {…}]
index: null
isBufferGeometry: true
morphAttributes: {}
morphTargetsRelative: false
name: ""
parameters: {shapes: Array(1), options: {…}}
type: "TextGeometry"
Related
Trying to pass an array of vec3s to the shader, Firefox gives me this warning:
WebGL warning: uniform setter: (uniform u_colors[0]) 'values' length
(4) must be a positive integer multiple of size of <enum 0x8b51>.
Also, it only renders black, not the given color.
const colrs = [
[239, 71, 111],
[255, 209, 102],
[6, 214, 160],
[17, 138, 178]
],
dmnsn = [1200, 300],
glCtx = (() => twgl.getContext(document.createElement("canvas")))(
twgl.setDefaults({ attribPrefix: "a_" })
);
var bfInf = twgl.primitives.createXYQuadBufferInfo(glCtx),
pgInf = twgl.createProgramInfo(glCtx, ["vs", "fs"]);
function rendr(fbi, pi, u) {
twgl.bindFramebufferInfo(glCtx, fbi);
twgl.drawObjectList(glCtx, [
{
programInfo: pi,
bufferInfo: bfInf,
uniforms: u
}
]);
}
function prepr() {
glCtx.canvas.width = dmnsn[0];
glCtx.canvas.height = dmnsn[1];
document.body.append(glCtx.canvas);
rendr(null, pgInf, { u_colors: colrs });
}
prepr();
<script src="https://twgljs.org/dist/4.x/twgl-full.min.js"></script>
<script id="vs" type="x-shader/x-vertex">
attribute vec4 a_position;
attribute vec2 a_texcoord;
varying vec2 v_texcoord;
void main() {
v_texcoord = a_texcoord;
gl_Position = a_position;
}
</script>
<script id="fs" type="x-shader/x-fragment">
precision highp float;
uniform vec3 u_colors[4];
void main() {
gl_FragColor= vec4(u_colors[0], 1.0);
}
</script>
WebGL does not want an array of arrays.
const someArrayWith4ArraysOf3Values = [
[11, 22, 33],
[44, 55, 66],
[77, 88, 99],
[10, 11, 12],
];
gl.uniform3fv(some4ElementVec3Uniform, someArrayWith4ArraysOf3Values); // bad
It wants a flat array.
const someArrayWith12Values = [
11, 22, 33,
44, 55, 66,
77, 88, 99,
10, 11, 12,
];
gl.uniform3fv(some4ElementVec3Uniform, someArrayWith12Values); // good
Also, colors in shaders are float values that go from 0 to 1 so you probably want to set your colors to values from 0 to 1 or divide by 255 in your shader
const colrs = [
[1, 0.7, 0.5],
[255, 209, 102],
[6, 214, 160],
[17, 138, 178]
].flat(),
dmnsn = [1200, 300],
glCtx = (() => twgl.getContext(document.createElement("canvas")))(
twgl.setDefaults({ attribPrefix: "a_" })
);
var bfInf = twgl.primitives.createXYQuadBufferInfo(glCtx),
pgInf = twgl.createProgramInfo(glCtx, ["vs", "fs"]);
function rendr(fbi, pi, u) {
twgl.bindFramebufferInfo(glCtx, fbi);
twgl.drawObjectList(glCtx, [
{
programInfo: pi,
bufferInfo: bfInf,
uniforms: u
}
]);
}
function prepr() {
glCtx.canvas.width = dmnsn[0];
glCtx.canvas.height = dmnsn[1];
document.body.append(glCtx.canvas);
rendr(null, pgInf, { u_colors: colrs });
}
prepr();
<script src="https://twgljs.org/dist/4.x/twgl-full.min.js"></script>
<script id="vs" type="x-shader/x-vertex">
attribute vec4 a_position;
attribute vec2 a_texcoord;
varying vec2 v_texcoord;
void main() {
v_texcoord = a_texcoord;
gl_Position = a_position;
}
</script>
<script id="fs" type="x-shader/x-fragment">
precision highp float;
uniform vec3 u_colors[4];
void main() {
gl_FragColor=vec4(u_colors[0], 1.0);
}
</script>
I try to create some object that a user could able by mouse rotate use Three.js and webgl. It's displaying fine when a screen has a full HD resolution (1960x1080) but when a user screen had resolution roughly 1366x768 object is ugly (blurred). Most notably text on the image.
Originally image has the resolution 1024x748 and the scene has a size roughly 530x270.
Clear - https://ibb.co/0s7W2hk
Blurred - https://ibb.co/tzCkq6W (in some cases blur corruption have more influence)
I connect the model to the scene by next code
// ...
scene.add({
genotype: VOLUMETRIC_OBJECT,
phenotype: MODELLED_MESH,
data: {
model: 'assets/FBX 2013/model.FBX',
position: {
x: 0,
y: isMobile ? 0.05 : 0.375,
z: 0,
},
scale: isMobile ? {
x: 70e-3,
y: 70e-3,
z: 70e-3,
} : {
x: 75e-3,
y: 75e-3,
z: 75e-3,
},
name: 'model',
material: {
hb_03_label1Model: {
map: 'assets/mm1.jpg',
alphaMap: 'assets/mam1.jpg',
color: 0xffffff,
specular: new Color(0xffffff),
shininess: 5,
transparent: true,
opacity: 1,
needsUpdate: true,
},
body_hb_03Model: {
normalMap: 'assets/mnm2.jpg',
color: 0xaaaaaa,
specular: new Color(0xFFFFFF),
opacity: 0.35,
shininess: 100,
transparent: true,
needsUpdate: true,
normalScale: {
x: 1,
y: 1,
},
},
hb_03_leqidoModel: {
type: MATERIAL__SHADER,
map: 'assets/mm3.jpg',
thicknessMap: 'assets/mtm3.jpg',
specularMap: 'assets/msm3.jpg',
normalMap: 'assets/mnm3.jpg',
repeat: [10, 10],
color: 0xffffff,
refractionRatio: 0.985,
reflectivity: 0.15,
diffuse: new Vector3(1, 0.3, 0.3),
thicknessColor: new Vector3(0.11, 0.11, 0.11),
needsUpdate: true,
uniformsNeedUpdate: true,
},
hb_03_cappaModel: {
color: 0x00AD16,
needsUpdate: true,
},
},
},
},
(model) => {
// ...
},
)
Update 1:
In my case when I change mag and min filters to Linear, I have strong sharpness and text not readable, again.
I think, for the best result, I need to use mag filter as Linear and min filter as LinearMipMapLinearFilter with the generated by myself mipmap.
But, currently, generate custom mipmap so strong for me. I did increase anisotropy for texture, and text is displayed acceptable
I'm hoping someone can clarify what is happening behind the scenes here.
I have an object that I am loading via the following method:
var loader = new THREE.FBXLoader();
loader.load( '../assets/models/Windia_C4D_Export.fbx', function ( object ) {
//loader.load( '../assets/models/quiggles_AR.fbx', function ( object ) {
console.log(object);
object.traverse( function ( child ) {
console.log(child);
if ( child.isMesh ) {
const oldMat = child.material;
//CONVERT MATERIAL TO STANDARD MATERIAL.
child.material = new THREE.MeshStandardMaterial({
color: oldMat.color,
map: oldMat.map,
});
child.castShadow = true;
child.receiveShadow = true;
child.material.combine = THREE.MixOperation;
child.material.envMap = envMap;
child.material.shininess=10;
child.material.refractionRatio=.5;
child.material.reflectivity=0.1;
//child.material.normalMap = texture;
//child.material.normalMapType = 0;
child.material.metalness=1;
//child.material.color.setHex( 0xffffff );
var sphereAxis = new THREE.AxesHelper(200);
child.add(sphereAxis);
}
} );
console.log(object);
object.scale.set(1,1,1);
scene.add( object );
} );
After iterating over all the children that are loaded and applying the same THREE.AxesHelper to each child that is a mesh object, every axeshelper is at the same position 0,0,0 instead of being aligned with the child they are associated with.
This is the result of logging the loaded object:
Group {uuid: "FBBF7E4B-7754-4138-BF1D-729398C2FB57", name: "VSM890D050Z05S22SN12_obj", type: "Group", parent: Group, children: Array(12), …}
ID: 140463347645952
animations: undefined
castShadow: false
children: (12) [Mesh, Mesh, Mesh, Mesh, Mesh, Mesh, Mesh, Mesh, Mesh, Mesh, Mesh, Mesh]
frustumCulled: true
layers: Layers {mask: 1}
matrix: Matrix4 {elements: Array(16)}
matrixAutoUpdate: true
matrixWorld: Matrix4 {elements: Array(16)}
matrixWorldNeedsUpdate: false
name: "VSM890D050Z05S22SN12_obj"
parent: Scene {uuid: "2D5254A0-ECA2-48D7-93D3-E0DD23E31277", name: "", type: "Scene", parent: null, children: Array(4), …}
position: Vector3 {x: 0, y: 0, z: 0}
quaternion: Quaternion {_x: 0, _y: 0, _z: 0, _w: 1, onChangeCallback: ƒ}
receiveShadow: false
renderOrder: 0
rotation: Euler {_x: -0, _y: 0, _z: -0, _order: "XYZ", onChangeCallback: ƒ}
scale: Vector3 {x: 1, y: 1, z: 1}
type: "Group"
up: Vector3 {x: 0, y: 1, z: 0}
userData: {transformData: {…}}
uuid: "FBBF7E4B-7754-4138-BF1D-729398C2FB57"
visible: true
eulerOrder: (...)
id: 17
modelViewMatrix: Matrix4 {elements: Array(16)}
normalMatrix: Matrix3 {elements: Array(9)}
useQuaternion: (...)
__proto__: Object3D
The following are expanded views of the first 2 child meshes in the group above. You can see the position of the axes helper are identical even though the items are in a different position within the loaded model.
Group {uuid: "FBBF7E4B-7754-4138-BF1D-729398C2FB57", name: "VSM890D050Z05S22SN12_obj", type: "Group", parent: Group, children: Array(12), …}
ID: 140463347645952
animations: undefined
castShadow: false
children: Array(12)
0: Mesh
ID: 140463347532800
castShadow: true
children: Array(1)
0: AxesHelper
castShadow: false
children: []
frustumCulled: true
geometry: BufferGeometry {uuid: "D2B77D74-2F72-4EC5-BBA3-B76A70E6C5D0", name: "", type: "BufferGeometry", index: null, attributes: {…}, …}
layers: Layers {mask: 1}
material: LineBasicMaterial {uuid: "253322F5-E482-4713-AF9B-D28DE8A06C35", name: "", type: "LineBasicMaterial", fog: true, lights: false, …}
matrix: Matrix4 {elements: Array(16)}
matrixAutoUpdate: true
matrixWorld: Matrix4 {elements: Array(16)}
matrixWorldNeedsUpdate: false
name: ""
parent: Mesh {uuid: "6A310982-D8A0-43B8-98F0-75C2B88BF8AE", name: "VSM890D050Z05S22SN12_11", type: "Mesh", parent: Group, children: Array(1), …}
position: Vector3 {x: 0, y: 0, z: 0}
quaternion: Quaternion {_x: 0, _y: 0, _z: 0, _w: 1, onChangeCallback: ƒ}
receiveShadow: false
renderOrder: 0
rotation: Euler {_x: 0, _y: 0, _z: 0, _order: "XYZ", onChangeCallback: ƒ}
scale: Vector3 {x: 1, y: 1, z: 1}
type: "LineSegments"
up: Vector3 {x: 0, y: 1, z: 0}
userData: {}
uuid: "3C46906A-BDBF-42D7-9608-52B7D9228271"
visible: true
eulerOrder: (...)
id: 30
modelViewMatrix: Matrix4 {elements: Array(16)}
normalMatrix: Matrix3 {elements: Array(9)}
useQuaternion: (...)
__proto__: LineSegments
length: 1
__proto__: Array(0)
drawMode: 0
frustumCulled: true
geometry: BufferGeometry {uuid: "ED7C9B64-2824-4364-AA97-3F92B00AC904", name: "", type: "BufferGeometry", index: null, attributes: {…}, …}
layers: Layers {mask: 1}
material: MeshStandardMaterial {uuid: "7BD69404-BFFF-4C54-A025-28F93AC84082", name: "", type: "MeshStandardMaterial", fog: true, lights: true, …}
matrix: Matrix4 {elements: Array(16)}
matrixAutoUpdate: true
matrixWorld: Matrix4 {elements: Array(16)}
matrixWorldNeedsUpdate: false
name: "VSM890D050Z05S22SN12_11"
parent: Group {uuid: "FBBF7E4B-7754-4138-BF1D-729398C2FB57", name: "VSM890D050Z05S22SN12_obj", type: "Group", parent: Scene, children: Array(12), …}
position: Vector3 {x: 0, y: 0, z: 0}
quaternion: Quaternion {_x: 0, _y: 0, _z: 0, _w: 1, onChangeCallback: ƒ}
receiveShadow: true
renderOrder: 0
rotation: Euler {_x: -0, _y: 0, _z: -0, _order: "XYZ", onChangeCallback: ƒ}
scale: Vector3 {x: 1, y: 1, z: 1}
type: "Mesh"
up: Vector3 {x: 0, y: 1, z: 0}
userData: {transformData: {…}}
uuid: "6A310982-D8A0-43B8-98F0-75C2B88BF8AE"
visible: true
eulerOrder: (...)
id: 18
modelViewMatrix: Matrix4 {elements: Array(16)}
normalMatrix: Matrix3 {elements: Array(9)}
useQuaternion: (...)
__proto__: Object3D
1: Mesh
ID: 140463525802496
castShadow: true
children: Array(1)
0: AxesHelper
castShadow: false
children: []
frustumCulled: true
geometry: BufferGeometry {uuid: "8D681768-AD23-49F4-BB4C-56ADB6A23695", name: "", type: "BufferGeometry", index: null, attributes: {…}, …}
layers: Layers {mask: 1}
material: LineBasicMaterial {uuid: "4DFCAAC0-F5A4-48B0-B417-FBEE4746E814", name: "", type: "LineBasicMaterial", fog: true, lights: false, …}
matrix: Matrix4 {elements: Array(16)}
matrixAutoUpdate: true
matrixWorld: Matrix4 {elements: Array(16)}
matrixWorldNeedsUpdate: false
name: ""
parent: Mesh {uuid: "D43C3C58-F4DE-4825-AA43-0BE94A5F536B", name: "VSM890D050Z05S22SN12_10", type: "Mesh", parent: Group, children: Array(1), …}
position: Vector3 {x: 0, y: 0, z: 0}
quaternion: Quaternion {_x: 0, _y: 0, _z: 0, _w: 1, onChangeCallback: ƒ}
receiveShadow: false
renderOrder: 0
rotation: Euler {_x: 0, _y: 0, _z: 0, _order: "XYZ", onChangeCallback: ƒ}
scale: Vector3 {x: 1, y: 1, z: 1}
type: "LineSegments"
up: Vector3 {x: 0, y: 1, z: 0}
userData: {}
uuid: "90F56573-8EEC-4A93-A372-DEC40C5CBC38"
visible: true
eulerOrder: (...)
id: 31
modelViewMatrix: Matrix4 {elements: Array(16)}
normalMatrix: Matrix3 {elements: Array(9)}
useQuaternion: (...)
__proto__: LineSegments
length: 1
__proto__: Array(0)
drawMode: 0
frustumCulled: true
geometry: BufferGeometry {uuid: "FCD47BEB-751B-4D17-9936-DE7C30A00D53", name: "", type: "BufferGeometry", index: null, attributes: {…}, …}
layers: Layers {mask: 1}
material: MeshStandardMaterial {uuid: "64AB972B-4390-4E54-985B-433D24C09D4F", name: "", type: "MeshStandardMaterial", fog: true, lights: true, …}
matrix: Matrix4 {elements: Array(16)}
matrixAutoUpdate: true
matrixWorld: Matrix4 {elements: Array(16)}
matrixWorldNeedsUpdate: false
name: "VSM890D050Z05S22SN12_10"
parent: Group {uuid: "FBBF7E4B-7754-4138-BF1D-729398C2FB57", name: "VSM890D050Z05S22SN12_obj", type: "Group", parent: Scene, children: Array(12), …}
position: Vector3 {x: 0, y: 0, z: 0}
quaternion: Quaternion {_x: 0, _y: 0, _z: 0, _w: 1, onChangeCallback: ƒ}
receiveShadow: true
renderOrder: 0
rotation: Euler {_x: -0, _y: 0, _z: -0, _order: "XYZ", onChangeCallback: ƒ}
scale: Vector3 {x: 1, y: 1, z: 1}
type: "Mesh"
up: Vector3 {x: 0, y: 1, z: 0}
userData: {transformData: {…}}
uuid: "D43C3C58-F4DE-4825-AA43-0BE94A5F536B"
visible: true
eulerOrder: (...)
id: 19
modelViewMatrix: Matrix4 {elements: Array(16)}
normalMatrix: Matrix3 {elements: Array(9)}
useQuaternion: (...)
__proto__: Object3D
This result leads me to believe the following:
AxesHelper relies upon the position of the object it is applied to. For whatever reason, the FBX object that is being loaded does not rely on independent positions of each child mesh object that is loaded. So when the FBX is loaded, all the children occupy the same 0,0,0 position (even though they are in different positions within the group). When the AxesHelper is applied to the child mesh, it occupies the same 0,0,0 position.
My question, is there a way for three.js to recognize or re-compute the position of all child meshes relative to the coordinate space within the group?
Is there another way to correct this? Is it a limitation of the FBX loader?
I'm using THREE.WebGLRenderer 97.
It looks like your objects' origins are positioned at 0, 0, 0 but the geometry is elsewhere. You should use the .computeBoundingBox() method to find where your geometry is, then you can use its .boundingBox property to access those coordinates.
// First, you must compute the geometry's bounds
child.geometry.computeBoundingBox();
// Get boundingBox prperty
var bounds = child.geometry.boundingBox;
// Get center of boundingBox
var center = bounds.getCenter();
// Position axisHelper at center of geometry
var sphereAxis = new THREE.AxesHelper(200);
sphereAxis.position.copy(center);
child.add(sphereAxis);
You can access several different properties of the boundingBox. There's more details in the documentation
Currently I have a line chart with 2 columns on it. I'm always showing labels because I want it to show right away the details.
The problem is, when the value of the 1st column matches with the value of the 2dn column the labels overlap.
Is there a way to show the label for column 1 always ABOVE the first line and show the label for column 2 always BELOW the second line?
This is what I got right now:
var chart1 = c3.generate({ //large devices
bindto: '#chart',
data: {
columns: [
['Col1', -0.7, -0.1, 4.6, -2.0, 4.2, 4.3, 5.4, 5.0, 0.6, 4.2, 4.9, 2.8, 2.7],
['Col2', -1.5, -0.9, 4.0, -2.5, 3.7, 4.0, 5.1, 4.8, 0.6, 4.2, 4.9, 2.8, 2.7]
],
labels:{
format: function(value){
return value + '%'
}
}
},
axis: {
x: {
type: 'category',
categories: ['Feb-17', 'Mar-17', 'Apr-17', 'May-17', 'Jun-17', 'Jul-17', 'Aug-17', 'Sep-17', 'Oct-17', 'Nov-17', 'Dec-17', 'Jan-18', 'Feb-18']
},
y: {
show: false,
min: -8,
max: 8
},
},
grid: {
y: {
lines: [{
value: 0
}]
}
},
size: {
height: 240
}
});
I tried to set the Y position on the onredered method but label doesn't have a y prop.Also, I can't get the dot position, so I wouldn't know if the current Y position is above or below the line.
You can set y axis label and change its position by this option
y: {
label: {
text: 'Your Y Axis',
position: 'outer-middle'
}}
Check the official documentation for more info: http://c3js.org/reference.html#axis-y-label
UIButton animation title position changed suddenly (jumped to the left), I want to keep the title in the button center nearby always.
You can see the button title ("Login In") jumped to the left unexpected, which should be optimized.
Here is the code:
UIView.animate(withDuration: 1.5, delay: 0.0, usingSpringWithDamping: 0.2, initialSpringVelocity: 0.0, options: [], animations: {
self.loginButton.bounds.size.width -= 80.0
}){ (yes) in }
UIView.animate(withDuration: 0.33, delay: 0.0, usingSpringWithDamping: 0.7, initialSpringVelocity: 0.0, options: [], animations: {
self.loginButton.center.y -= 60.0
self.loginButton.backgroundColor = UIColor(red: 0.63, green: 0.84, blue: 0.35, alpha: 1.0)
self.spinner.center = CGPoint(x: -20, y: -16)
self.spinner.alpha = 0.0
}){ (yes) in }
Here is the code I tried , which does not work too.
UIView.animate(withDuration: 0.3, delay: 0.2, options: [], animations: {
self.loginButton.backgroundColor = UIColor(red: 0.63, green: 0.84, blue: 0.35, alpha: 1.0)
self.loginButton.bounds.size.width -= 80.0
self.loginButton.center.y -= 60.0
self.spinner.frame.origin = CGPoint(x: -20, y: 16)
self.spinner.alpha = 0.0
}) { (isOK) in }
PS:
I add the login button through storyboard , as the following image
And the code relevant is here
Add line in animation function
UIView.animate(withDuration: 1, delay: 0.2, options: [], animations: {
//Your code for animation
.
.
.
//Add this line
self.view.layoutIfNeeded()
}) { (isOK) in }
Note
Use Auto Layout for all device support and easy to animation