7

Trying to convert the following php method to use in a .less stylesheet:

<?php
    $deg2radians = pi() * 2 / 360;
    $rad = $degree * $deg2radians;
    $costheta = cos($rad);
    $sintheta = sin($rad);
?>

In Less, how I might one implement a sine/cosine method without using language-specific cos()/sin() functions?

.rotate(@deg) {
    // css transform capable browsers properties...

    // IE <= 8
    @deg2radians: 3.1416 * 2 / 360;
    @rad: @degree * @deg2radians;
    @sintheta: sin(@rad);             // How to sin()?
    @costheta: cos(@rad);             // How to cos()?

    // filter: transform matrix method...
}
tester
  • 22,441
  • 25
  • 88
  • 128
  • as a note, it would be ideal to not use any language-specific Math sine/cosine methods to solve this. If it can be done with basic math, that would make it work in separate implementations like dotless (asp.net), lessjs (JavaScript), etc... – tester May 11 '11 at 21:52
  • 3
    Sine and cosine are transcendental functions. Although they can be defined by power series, there is no exact formula in terms of finitely many arithmetic operations, but approximations of any desired accuracy can be defined using arithmetic. It's definitely a "reinvent the wheel" kind of thing, but if you're interested I'll give you some pointers on how to do it. – hardmath May 11 '11 at 22:46
  • 2
    @hardmath I find your name to be somewhat humorous in this situation. – voithos May 11 '11 at 23:27

2 Answers2

9

Well, it is not quite language-independent, but since it is just Javascript it should work in all the LESS implementations, unless I'm not thinking about this clearly.

That being said, you can use Javascript to calculate sine and cosine:

.rotate(@deg) {
    // css transform capable browsers properties...

    // IE <= 8
    @deg2radians: 3.1416 * 2 / 360;
    @rad: @degree * @deg2radians;
    @sintheta: ~`Math.sin(@{rad})`;
    @costheta: ~`Math.cos(@{rad})`;

    // filter: transform matrix method...
}

The backticks are used to evaluate Javascript, and you can actually access the DOM as well. For example, the following is perfectly allowed:

`document.write('Hello!')`

The tilde is used for escaping, and the @{} signifies variable interpolation. For example:

@input: 10;

`document.write(Math.sin(@{input}))`;

Check out the LESS usage guide for more info.

voithos
  • 68,482
  • 12
  • 101
  • 116
  • ah see, I was wondering if it was the entirety of Less that was written in JavaScript, or if it was just less.js that was the JavaScript version of less. I'll test that out in dotless (asp.net's implementation of less) right now – tester May 11 '11 at 23:20
  • ah so it turns out that the escape syntax is different in less.js @var: #f00; prop: e(%("stuff here %d"), @var); is prop: "stuff here #f00"; but in all other implementations it is ~foobar@{var}; – tester May 12 '11 at 00:45
  • @tester The syntax that you gave for less.js doesn't seem to interpolate Javascript, though. I'll try to test it later, if I have time, but it seems that the usage guide on their web site is out of date. – voithos May 12 '11 at 13:56
  • here's an example of the differences between string/var concat in lessjs vs dotless (or the less standard): https://github.com/dancrew32/lesslib/blob/master/mixins.less#L69-72 . =/ – tester May 12 '11 at 17:30
  • (just noticed you updated the answer) ah, so that's how/when to implement @{varName}. Thanks for clearing that part up. – tester May 12 '11 at 17:32
2

Back-ticks do not seem to be working in dotless. You will get "[script unsupported]" in the output. The way I came up with solving the cos/sin problem in dotless was to implement function extensions. You can see an example of a function extension here: https://groups.google.com/forum/?fromgroups=#!topic/dotless/3fVydO8mTHw. Wouter Boevink had a question with configuring this in Asp.Net, which he himself answers further down in the discussion. Also look at the implementation for dotless.Core.Parser.Functions.AbsFunction to see how to implement a simple numeric function.

VeeTheSecond
  • 3,086
  • 3
  • 20
  • 16